patch-2.4.0-test11 linux/net/irda/irlap_event.c
Next file: linux/net/irda/irlap_frame.c
Previous file: linux/net/irda/irlap_comp.c
Back to the patch index
Back to the overall index
- Lines: 711
- Date:
Sat Nov 11 18:11:23 2000
- Orig file:
v2.4.0-test10/linux/net/irda/irlap_event.c
- Orig date:
Thu Jan 6 14:46:18 2000
diff -u --recursive --new-file v2.4.0-test10/linux/net/irda/irlap_event.c linux/net/irda/irlap_event.c
@@ -9,8 +9,8 @@
* Modified at: Sat Dec 25 21:07:57 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
- * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
- * Thomas Davis <ratbert@radiks.net>
+ * Copyright (c) 1998-2000 Dag Brattli <dag@brattli.net>,
+ * Copyright (c) 1998 Thomas Davis <ratbert@radiks.net>
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
@@ -230,7 +230,7 @@
if (!self || self->magic != LAP_MAGIC)
return;
-
+
IRDA_DEBUG(3, __FUNCTION__ "(), event = %s, state = %s\n",
irlap_event[event], irlap_state[self->state]);
@@ -252,6 +252,7 @@
while ((skb = skb_dequeue(&self->txq)) != NULL) {
ret = (*state[self->state])(self, SEND_I_CMD,
skb, NULL);
+ kfree_skb(skb);
if (ret == -EPROTO)
break; /* Try again later! */
}
@@ -304,6 +305,17 @@
if ((state != LAP_XMIT_P) && (state != LAP_XMIT_S))
self->bytes_left = self->line_capacity;
#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
+#ifdef CONFIG_IRDA_ULTRA
+ /* Send any pending Ultra frames if any */
+ /* The higher layers may have sent a few Ultra frames while we
+ * were doing discovery (either query or reply). Those frames
+ * have been queued, but were never sent. It is now time to
+ * send them...
+ * Jean II */
+ if ((state == LAP_NDM) && (!skb_queue_empty(&self->txq_ultra)))
+ /* Force us to listen 500 ms before sending Ultra */
+ irda_device_set_media_busy(self->netdev, TRUE);
+#endif /* CONFIG_IRDA_ULTRA */
}
/*
@@ -351,12 +363,11 @@
self->caddr = info->caddr;
irlap_next_state(self, LAP_CONN);
-
+
irlap_connect_indication(self, skb);
} else {
IRDA_DEBUG(0, __FUNCTION__ "(), SNRM frame does not "
"contain an I field!\n");
- dev_kfree_skb(skb);
}
break;
case DISCOVERY_REQUEST:
@@ -375,6 +386,7 @@
self->s = info->s;
irlap_send_discovery_xid_frame(self, info->S, info->s, TRUE,
info->discovery);
+ self->frame_sent = FALSE;
self->s++;
irlap_start_slot_timer(self, self->slot_timeout);
@@ -385,12 +397,8 @@
/* Assert that this is not the final slot */
if (info->s <= info->S) {
- /* self->daddr = info->daddr; */
self->slot = irlap_generate_rand_time_slot(info->S,
info->s);
- IRDA_DEBUG(4, "XID_CMD: S=%d, s=%d, slot %d\n", info->S,
- info->s, self->slot);
-
if (self->slot == info->s) {
discovery_rsp = irlmp_get_discovery_response();
discovery_rsp->daddr = info->daddr;
@@ -410,14 +418,34 @@
irlap_start_query_timer(self, QUERY_TIMEOUT*info->S);
irlap_next_state(self, LAP_REPLY);
}
- dev_kfree_skb(skb);
+ else {
+ /* This is the final slot. How is it possible ?
+ * This would happen is both discoveries are just slightly
+ * offset (if they are in sync, all packets are lost).
+ * Most often, all the discovery requests will be received
+ * in QUERY state (see my comment there), except for the
+ * last frame that will come here.
+ * The big trouble when it happen is that active discovery
+ * doesn't happen, because nobody answer the discoveries
+ * frame of the other guy, so the log shows up empty.
+ * What should we do ?
+ * Not much. It's too late to answer those discovery frames,
+ * so we just pass the info to IrLMP who will put it in the
+ * log (and post an event).
+ * Jean II
+ */
+ IRDA_DEBUG(1, __FUNCTION__ "(), Receiving final discovery request, missed the discovery slots :-(\n");
+
+ /* Last discovery request -> in the log */
+ irlap_discovery_indication(self, info->discovery);
+ }
break;
#ifdef CONFIG_IRDA_ULTRA
case SEND_UI_FRAME:
/* Only allowed to repeat an operation twice */
for (i=0; ((i<2) && (self->media_busy == FALSE)); i++) {
skb = skb_dequeue(&self->txq_ultra);
- if (skb)
+ if (skb)
irlap_send_ui_frame(self, skb, CBROADCAST,
CMD_FRAME);
else
@@ -433,7 +461,6 @@
if (info->caddr != CBROADCAST) {
IRDA_DEBUG(0, __FUNCTION__
"(), not a broadcast frame!\n");
- dev_kfree_skb(skb);
} else
irlap_unitdata_indication(self, skb);
break;
@@ -447,19 +474,14 @@
* will only be used to send out the same info as the cmd
*/
irlap_send_test_frame(self, CBROADCAST, info->daddr, skb);
- dev_kfree_skb(skb);
break;
case RECV_TEST_RSP:
IRDA_DEBUG(0, __FUNCTION__ "() not implemented!\n");
- dev_kfree_skb(skb);
break;
default:
IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %s\n",
irlap_event[event]);
- if (skb)
- dev_kfree_skb(skb);
-
ret = -1;
break;
}
@@ -492,19 +514,51 @@
WARNING(__FUNCTION__ "(), discovery log is gone! "
"maybe the discovery timeout has been set to "
"short?\n");
- dev_kfree_skb(skb);
break;
}
hashbin_insert(self->discovery_log,
- (queue_t *) info->discovery,
+ (irda_queue_t *) info->discovery,
info->discovery->daddr, NULL);
/* Keep state */
/* irlap_next_state(self, LAP_QUERY); */
- dev_kfree_skb(skb);
+ break;
+ case RECV_DISCOVERY_XID_CMD:
+ /* Yes, it is possible to receive those frames in this mode.
+ * Note that most often the last discovery request won't
+ * occur here but in NDM state (see my comment there).
+ * What should we do ?
+ * Not much. We are currently performing our own discovery,
+ * therefore we can't answer those frames. We don't want
+ * to change state either. We just pass the info to
+ * IrLMP who will put it in the log (and post an event).
+ * Jean II
+ */
+
+ ASSERT(info != NULL, return -1;);
+
+ IRDA_DEBUG(1, __FUNCTION__ "(), Receiving discovery request (s = %d) while performing discovery :-(\n", info->s);
+
+ /* Last discovery request ? */
+ if (info->s == 0xff)
+ irlap_discovery_indication(self, info->discovery);
break;
case SLOT_TIMER_EXPIRED:
+ /*
+ * Wait a little longer if we detect an incomming frame. This
+ * is not mentioned in the spec, but is a good thing to do,
+ * since we want to work even with devices that violate the
+ * timing requirements.
+ */
+ if (irda_device_is_receiving(self->netdev)) {
+ IRDA_DEBUG(1, __FUNCTION__
+ "(), device is slow to answer, "
+ "waiting some more!\n");
+ irlap_start_slot_timer(self, MSECS_TO_JIFFIES(10));
+ return ret;
+ }
+
if (self->s < self->S) {
irlap_send_discovery_xid_frame(self, self->S,
self->s, TRUE,
@@ -537,9 +591,6 @@
IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %s\n",
irlap_event[event]);
- if (skb)
- dev_kfree_skb(skb);
-
ret = -1;
break;
}
@@ -572,9 +623,7 @@
break;
case RECV_DISCOVERY_XID_CMD:
ASSERT(info != NULL, return -1;);
- /*
- * Last frame?
- */
+ /* Last frame? */
if (info->s == 0xff) {
del_timer(&self->query_timer);
@@ -595,15 +644,11 @@
self->frame_sent = TRUE;
irlap_next_state(self, LAP_REPLY);
}
- dev_kfree_skb(skb);
break;
default:
IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event,
irlap_event[event]);
- if (skb)
- dev_kfree_skb(skb);
-
ret = -1;
break;
}
@@ -665,14 +710,12 @@
irlap_start_wd_timer(self, self->wd_timeout);
irlap_next_state(self, LAP_NRM_S);
- dev_kfree_skb(skb);
break;
case RECV_DISCOVERY_XID_CMD:
IRDA_DEBUG(3, __FUNCTION__
"(), event RECV_DISCOVER_XID_CMD!\n");
irlap_next_state(self, LAP_NDM);
- dev_kfree_skb(skb);
break;
case DISCONNECT_REQUEST:
irlap_send_dm_frame(self);
@@ -682,9 +725,6 @@
IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event,
irlap_event[event]);
- if (skb)
- dev_kfree_skb(skb);
-
ret = -1;
break;
}
@@ -766,7 +806,6 @@
irlap_start_wd_timer(self, self->wd_timeout);
} else {
/* We just ignore the other device! */
- dev_kfree_skb(skb);
irlap_next_state(self, LAP_SETUP);
}
break;
@@ -803,14 +842,11 @@
irlap_next_state(self, LAP_NDM);
irlap_disconnect_indication(self, LAP_DISC_INDICATION);
- dev_kfree_skb(skb);
break;
default:
IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event,
irlap_event[event]);
- if (skb)
- dev_kfree_skb(skb);
-
+
ret = -1;
break;
}
@@ -860,14 +896,13 @@
IRDA_DEBUG(4, __FUNCTION__
"(), Not allowed to transmit more "
"bytes!\n");
- skb_queue_head(&self->txq, skb);
-
+ skb_queue_head(&self->txq, skb_get(skb));
/*
* We should switch state to LAP_NRM_P, but
* that is not possible since we must be sure
* that we poll the other side. Since we have
* used up our time, the poll timer should
- * trigger anyway now,so we just wait for it
+ * trigger anyway now, so we just wait for it
* DB
*/
return -EPROTO;
@@ -900,7 +935,7 @@
} else {
IRDA_DEBUG(4, __FUNCTION__
"(), Unable to send! remote busy?\n");
- skb_queue_head(&self->txq, skb);
+ skb_queue_head(&self->txq, skb_get(skb));
/*
* The next ret is important, because it tells
@@ -929,9 +964,6 @@
IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n",
irlap_event[event]);
- if (skb)
- dev_kfree_skb(skb);
-
ret = -EINVAL;
break;
}
@@ -964,7 +996,6 @@
irlap_next_state(self, LAP_NDM);
irlap_disconnect_indication(self, LAP_DISC_INDICATION);
- dev_kfree_skb(skb);
break;
case FINAL_TIMER_EXPIRED:
if (self->retry_count < self->N3) {
@@ -985,9 +1016,6 @@
default:
IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d\n", event);
- if (skb)
- dev_kfree_skb(skb);
-
ret = -1;
break;
}
@@ -1041,7 +1069,7 @@
/* Keep state, do not move this line */
irlap_next_state(self, LAP_NRM_P);
-
+
irlap_data_indication(self, skb, FALSE);
} else {
del_timer(&self->final_timer);
@@ -1065,7 +1093,7 @@
* upper layers
*/
irlap_next_state(self, LAP_XMIT_P);
-
+
irlap_data_indication(self, skb, FALSE);
/* This is the last frame */
@@ -1102,7 +1130,6 @@
irlap_start_final_timer(self, self->final_timeout);
irlap_next_state(self, LAP_NRM_P);
}
- dev_kfree_skb(skb);
break;
}
/*
@@ -1124,7 +1151,7 @@
/* Keep state, do not move this line */
irlap_next_state(self, LAP_NRM_P);
-
+
irlap_data_indication(self, skb, FALSE);
} else {
/*
@@ -1142,7 +1169,7 @@
/* Keep state, do not move this line!*/
irlap_next_state(self, LAP_NRM_P);
-
+
irlap_data_indication(self, skb, FALSE);
}
break;
@@ -1171,7 +1198,6 @@
self->ack_required = FALSE;
}
- dev_kfree_skb(skb);
break;
}
@@ -1193,7 +1219,6 @@
self->xmitflag = FALSE;
}
- dev_kfree_skb(skb);
break;
}
IRDA_DEBUG(1, __FUNCTION__ "(), Not implemented!\n");
@@ -1209,6 +1234,7 @@
} else {
del_timer(&self->final_timer);
irlap_data_indication(self, skb, TRUE);
+ printk(__FUNCTION__ "(): RECV_UI_FRAME: next state %s\n", irlap_state[self->state]);
irlap_start_poll_timer(self, self->poll_timeout);
}
break;
@@ -1270,7 +1296,6 @@
irlap_disconnect_indication(self, LAP_RESET_INDICATION);
self->xmitflag = TRUE;
}
- dev_kfree_skb(skb);
break;
case RECV_RNR_RSP:
ASSERT(info != NULL, return -1;);
@@ -1285,14 +1310,12 @@
/* Start poll timer */
irlap_start_poll_timer(self, self->poll_timeout);
- dev_kfree_skb(skb);
break;
case RECV_FRMR_RSP:
del_timer(&self->final_timer);
self->xmitflag = TRUE;
irlap_next_state(self, LAP_RESET_WAIT);
irlap_reset_indication(self);
- dev_kfree_skb(skb);
break;
case FINAL_TIMER_EXPIRED:
/*
@@ -1331,7 +1354,7 @@
" retry_count=%d\n", self->retry_count);
/* Keep state */
} else if (self->retry_count == self->N1) {
- irlap_status_indication(STATUS_NO_ACTIVITY);
+ irlap_status_indication(self, STATUS_NO_ACTIVITY);
irlap_wait_min_turn_around(self, &self->qos_tx);
irlap_send_rr_frame(self, CMD_FRAME);
@@ -1357,7 +1380,6 @@
} else
irlap_resend_rejected_frames(self, CMD_FRAME);
irlap_start_final_timer(self, self->final_timeout);
- dev_kfree_skb(skb);
break;
case RECV_SREJ_RSP:
irlap_update_nr_received(self, info->nr);
@@ -1367,7 +1389,6 @@
} else
irlap_resend_rejected_frame(self, CMD_FRAME);
irlap_start_final_timer(self, self->final_timeout);
- dev_kfree_skb(skb);
break;
case RECV_RD_RSP:
IRDA_DEBUG(0, __FUNCTION__ "(), RECV_RD_RSP\n");
@@ -1381,8 +1402,6 @@
default:
IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %s\n",
irlap_event[event]);
- if (skb)
- dev_kfree_skb(skb);
ret = -1;
break;
@@ -1428,10 +1447,8 @@
irlap_next_state( self, LAP_PCLOSE);
break;
default:
- IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %s\n",
+ IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %s\n",
irlap_event[event]);
- if (skb)
- dev_kfree_skb(skb);
ret = -1;
break;
@@ -1467,7 +1484,6 @@
irlap_disconnect_indication(self, LAP_NO_RESPONSE);
- dev_kfree_skb(skb);
break;
case RECV_UA_RSP:
del_timer(&self->final_timer);
@@ -1483,7 +1499,6 @@
irlap_start_poll_timer(self, self->poll_timeout);
- dev_kfree_skb(skb);
break;
case FINAL_TIMER_EXPIRED:
if (self->retry_count < 3) {
@@ -1522,13 +1537,10 @@
IRDA_DEBUG(0, __FUNCTION__
"(), SNRM frame contained an I field!\n");
}
- dev_kfree_skb(skb);
break;
default:
IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %s\n",
irlap_event[event]);
- if (skb)
- dev_kfree_skb(skb);
ret = -1;
break;
@@ -1566,7 +1578,7 @@
* speed and turn-around-time.
*/
if (skb->len > self->bytes_left) {
- skb_queue_head(&self->txq, skb);
+ skb_queue_head(&self->txq, skb_get(skb));
/*
* Switch to NRM_S, this is only possible
* when we are in secondary mode, since we
@@ -1600,7 +1612,7 @@
}
} else {
IRDA_DEBUG(2, __FUNCTION__ "(), Unable to send!\n");
- skb_queue_head(&self->txq, skb);
+ skb_queue_head(&self->txq, skb_get(skb));
ret = -EPROTO;
}
break;
@@ -1613,8 +1625,6 @@
default:
IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %s\n",
irlap_event[event]);
- if (skb)
- dev_kfree_skb(skb);
ret = -EINVAL;
break;
@@ -1676,7 +1686,7 @@
#endif
/* Keep state, do not move this line */
irlap_next_state(self, LAP_NRM_S);
-
+
irlap_data_indication(self, skb, FALSE);
break;
} else {
@@ -1739,7 +1749,6 @@
irlap_start_wd_timer(self, self->wd_timeout);
}
- dev_kfree_skb(skb);
break;
}
@@ -1778,7 +1787,7 @@
/* Keep state, do not move this line */
irlap_next_state(self, LAP_NRM_S);
-
+
irlap_data_indication(self, skb, FALSE);
irlap_start_wd_timer(self, self->wd_timeout);
}
@@ -1787,11 +1796,9 @@
if (ret == NR_INVALID) {
IRDA_DEBUG(0, "NRM_S, NR_INVALID not implemented!\n");
- dev_kfree_skb(skb);
}
if (ret == NS_INVALID) {
IRDA_DEBUG(0, "NRM_S, NS_INVALID not implemented!\n");
- dev_kfree_skb(skb);
}
break;
case RECV_UI_FRAME:
@@ -1870,7 +1877,6 @@
IRDA_DEBUG(1, __FUNCTION__
"(), invalid nr not implemented!\n");
}
- dev_kfree_skb(skb);
break;
case RECV_SNRM_CMD:
/* SNRM frame is not allowed to contain an I-field */
@@ -1885,7 +1891,6 @@
"(), SNRM frame contained an I-field!\n");
}
- dev_kfree_skb(skb);
break;
case RECV_REJ_CMD:
irlap_update_nr_received(self, info->nr);
@@ -1895,7 +1900,6 @@
} else
irlap_resend_rejected_frames(self, CMD_FRAME);
irlap_start_wd_timer(self, self->wd_timeout);
- dev_kfree_skb(skb);
break;
case RECV_SREJ_CMD:
irlap_update_nr_received(self, info->nr);
@@ -1905,31 +1909,34 @@
} else
irlap_resend_rejected_frame(self, CMD_FRAME);
irlap_start_wd_timer(self, self->wd_timeout);
- dev_kfree_skb(skb);
break;
case WD_TIMER_EXPIRED:
/*
* Wait until retry_count * n matches negotiated threshold/
* disconnect time (note 2 in IrLAP p. 82)
+ *
+ * Note : self->wd_timeout = (self->poll_timeout * 2),
+ * and self->final_timeout == self->poll_timeout,
+ * which explain why we use (self->retry_count * 2) here !!!
+ * Jean II
*/
IRDA_DEBUG(1, __FUNCTION__ "(), retry_count = %d\n",
self->retry_count);
- if ((self->retry_count < (self->N2/2)) &&
- (self->retry_count != self->N1/2)) {
+ if (((self->retry_count * 2) < self->N2) &&
+ ((self->retry_count * 2) != self->N1)) {
irlap_start_wd_timer(self, self->wd_timeout);
- self->retry_count++;
- } else if (self->retry_count == (self->N1/2)) {
- irlap_status_indication(STATUS_NO_ACTIVITY);
+ self->retry_count++;
+ } else if ((self->retry_count * 2) == self->N1) {
+ irlap_status_indication(self, STATUS_NO_ACTIVITY);
irlap_start_wd_timer(self, self->wd_timeout);
self->retry_count++;
- } else if (self->retry_count >= self->N2/2) {
+ } else if ((self->retry_count * 2) >= self->N2) {
irlap_apply_default_connection_parameters(self);
/* Always switch state before calling upper layers */
irlap_next_state(self, LAP_NDM);
-
irlap_disconnect_indication(self, LAP_NO_RESPONSE);
}
break;
@@ -1944,7 +1951,6 @@
irlap_apply_default_connection_parameters(self);
irlap_disconnect_indication(self, LAP_DISC_INDICATION);
- dev_kfree_skb(skb);
break;
case RECV_DISCOVERY_XID_CMD:
irlap_wait_min_turn_around(self, &self->qos_tx);
@@ -1953,24 +1959,20 @@
irlap_start_wd_timer(self, self->wd_timeout);
irlap_next_state(self, LAP_NRM_S);
- dev_kfree_skb(skb);
break;
case RECV_TEST_CMD:
- /* Remove test frame header */
- skb_pull(skb, sizeof(struct test_frame));
+ /* Remove test frame header (only LAP header in NRM) */
+ skb_pull(skb, LAP_ADDR_HEADER + LAP_CTRL_HEADER);
irlap_wait_min_turn_around(self, &self->qos_tx);
irlap_start_wd_timer(self, self->wd_timeout);
/* Send response (info will be copied) */
irlap_send_test_frame(self, self->caddr, info->daddr, skb);
- dev_kfree_skb(skb);
break;
default:
IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, (%s)\n",
event, irlap_event[event]);
- if (skb)
- dev_kfree_skb(skb);
ret = -EINVAL;
break;
@@ -2005,7 +2007,6 @@
irlap_apply_default_connection_parameters(self);
irlap_disconnect_indication(self, LAP_DISC_INDICATION);
- dev_kfree_skb(skb);
break;
case RECV_DM_RSP:
/* Always switch state before calling upper layers */
@@ -2015,7 +2016,6 @@
irlap_apply_default_connection_parameters(self);
irlap_disconnect_indication(self, LAP_DISC_INDICATION);
- dev_kfree_skb(skb);
break;
case WD_TIMER_EXPIRED:
irlap_apply_default_connection_parameters(self);
@@ -2025,9 +2025,7 @@
default:
IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, (%s)\n",
event, irlap_event[event]);
- if (skb)
- dev_kfree_skb(skb);
-
+
ret = -EINVAL;
break;
}
@@ -2064,8 +2062,6 @@
default:
IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, (%s)\n",
event, irlap_event[event]);
- if (skb)
- dev_kfree_skb(skb);
ret = -EINVAL;
break;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)