Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next 3/6] llc2: Collapse the station event receive path
From: Ben Hutchings @ 2012-09-16  3:11 UTC (permalink / raw)
  To: David S. Miller, Arnaldo Carvalho de Melo; +Cc: netdev
In-Reply-To: <1347764982.13258.207.camel@deadeye.wl.decadent.org.uk>

[-- Attachment #1: Type: text/plain, Size: 3942 bytes --]

We only ever put one skb on the event queue, and then immediately
process it.  Remove the queue and fold together the related functions,
removing several blatantly false comments.

Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 net/llc/llc_station.c |   87 ++++---------------------------------------------
 1 file changed, 6 insertions(+), 81 deletions(-)

diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c
index 917d700..3bdb888 100644
--- a/net/llc/llc_station.c
+++ b/net/llc/llc_station.c
@@ -32,14 +32,9 @@
  *
  * @mac_sa: MAC source address
  * @sap_list: list of related SAPs
- * @ev_q: events entering state mach.
  * @mac_pdu_q: PDUs ready to send to MAC
  */
 struct llc_station {
-	struct {
-		struct sk_buff_head list;
-		spinlock_t	    lock;
-	} ev_q;
 	struct sk_buff_head	    mac_pdu_q;
 };
 
@@ -216,79 +211,6 @@ static struct llc_station_state_trans *
 }
 
 /**
- *	llc_station_free_ev - frees an event
- *	@skb: Address of the event
- *
- *	Frees an event.
- */
-static void llc_station_free_ev(struct sk_buff *skb)
-{
-	kfree_skb(skb);
-}
-
-/**
- *	llc_station_next_state - processes event and goes to the next state
- *	@skb: Address of the event
- *
- *	Processes an event, executes any transitions related to that event and
- *	updates the state of the station.
- */
-static u16 llc_station_next_state(struct sk_buff *skb)
-{
-	u16 rc = 1;
-	struct llc_station_state_trans *trans;
-
-	trans = llc_find_station_trans(skb);
-	if (trans)
-		/* got the state to which we next transition; perform the
-		 * actions associated with this transition before actually
-		 * transitioning to the next state
-		 */
-		rc = llc_exec_station_trans_actions(trans, skb);
-	else
-		/* event not recognized in current state; re-queue it for
-		 * processing again at a later time; return failure
-		 */
-		rc = 0;
-	llc_station_free_ev(skb);
-	return rc;
-}
-
-/**
- *	llc_station_service_events - service events in the queue
- *
- *	Get an event from the station event queue (if any); attempt to service
- *	the event; if event serviced, get the next event (if any) on the event
- *	queue; if event not service, re-queue the event on the event queue and
- *	attempt to service the next event; when serviced all events in queue,
- *	finished; if don't transition to different state, just service all
- *	events once; if transition to new state, service all events again.
- *	Caller must hold llc_main_station.ev_q.lock.
- */
-static void llc_station_service_events(void)
-{
-	struct sk_buff *skb;
-
-	while ((skb = skb_dequeue(&llc_main_station.ev_q.list)) != NULL)
-		llc_station_next_state(skb);
-}
-
-/**
- *	llc_station_state_process - queue event and try to process queue.
- *	@skb: Address of the event
- *
- *	Queues an event (on the station event queue) for handling by the
- *	station state machine and attempts to process any queued-up events.
- */
-static void llc_station_state_process(struct sk_buff *skb)
-{
-	spin_lock_bh(&llc_main_station.ev_q.lock);
-	skb_queue_tail(&llc_main_station.ev_q.list, skb);
-	llc_station_service_events();
-	spin_unlock_bh(&llc_main_station.ev_q.lock);
-}
-
-/**
  *	llc_station_rcv - send received pdu to the station state machine
  *	@skb: received frame.
  *
@@ -296,14 +218,17 @@ static void llc_station_state_process(struct sk_buff *skb)
  */
 static void llc_station_rcv(struct sk_buff *skb)
 {
-	llc_station_state_process(skb);
+	struct llc_station_state_trans *trans;
+
+	trans = llc_find_station_trans(skb);
+	if (trans)
+		llc_exec_station_trans_actions(trans, skb);
+	kfree_skb(skb);
 }
 
 void __init llc_station_init(void)
 {
 	skb_queue_head_init(&llc_main_station.mac_pdu_q);
-	skb_queue_head_init(&llc_main_station.ev_q.list);
-	spin_lock_init(&llc_main_station.ev_q.lock);
 	llc_set_station_handler(llc_station_rcv);
 }
 



[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply related

* [PATCH net-next 2/6] llc2: Remove dead code for state machine
From: Ben Hutchings @ 2012-09-16  3:11 UTC (permalink / raw)
  To: David S. Miller, Arnaldo Carvalho de Melo; +Cc: netdev
In-Reply-To: <1347764982.13258.207.camel@deadeye.wl.decadent.org.uk>

[-- Attachment #1: Type: text/plain, Size: 17967 bytes --]

The initial state is UP and there is no way to enter the other states
as the required event type is never generated.  Delete all states,
event types, and other dead code.  The only thing left is handling
of the XID and TEST commands.

Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 net/llc/llc_station.c |  404 ++-----------------------------------------------
 1 file changed, 9 insertions(+), 395 deletions(-)

diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c
index e16c1b9..917d700 100644
--- a/net/llc/llc_station.c
+++ b/net/llc/llc_station.c
@@ -30,19 +30,12 @@
  *
  * SAP and connection resource manager, one per adapter.
  *
- * @state: state of station
- * @xid_r_count: XID response PDU counter
  * @mac_sa: MAC source address
  * @sap_list: list of related SAPs
  * @ev_q: events entering state mach.
  * @mac_pdu_q: PDUs ready to send to MAC
  */
 struct llc_station {
-	u8			    state;
-	u8			    xid_r_count;
-	struct timer_list	    ack_timer;
-	u8			    retry_count;
-	u8			    maximum_retry;
 	struct {
 		struct sk_buff_head list;
 		spinlock_t	    lock;
@@ -50,162 +43,38 @@ struct llc_station {
 	struct sk_buff_head	    mac_pdu_q;
 };
 
-#define LLC_STATION_ACK_TIME (3 * HZ)
-
-int sysctl_llc_station_ack_timeout = LLC_STATION_ACK_TIME;
-
-/* Types of events (possible values in 'ev->type') */
-#define LLC_STATION_EV_TYPE_SIMPLE	1
-#define LLC_STATION_EV_TYPE_CONDITION	2
-#define LLC_STATION_EV_TYPE_PRIM	3
-#define LLC_STATION_EV_TYPE_PDU		4       /* command/response PDU */
-#define LLC_STATION_EV_TYPE_ACK_TMR	5
-#define LLC_STATION_EV_TYPE_RPT_STATUS	6
-
-/* Events */
-#define LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK		1
-#define LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK		2
-#define LLC_STATION_EV_ACK_TMR_EXP_LT_RETRY_CNT_MAX_RETRY	3
-#define LLC_STATION_EV_ACK_TMR_EXP_EQ_RETRY_CNT_MAX_RETRY	4
-#define LLC_STATION_EV_RX_NULL_DSAP_XID_C			5
-#define LLC_STATION_EV_RX_NULL_DSAP_0_XID_R_XID_R_CNT_EQ	6
-#define LLC_STATION_EV_RX_NULL_DSAP_1_XID_R_XID_R_CNT_EQ	7
-#define LLC_STATION_EV_RX_NULL_DSAP_TEST_C			8
-#define LLC_STATION_EV_DISABLE_REQ				9
-
-struct llc_station_state_ev {
-	u8		 type;
-	u8		 prim;
-	u8		 prim_type;
-	u8		 reason;
-	struct list_head node; /* node in station->ev_q.list */
-};
-
-static __inline__ struct llc_station_state_ev *
-					llc_station_ev(struct sk_buff *skb)
-{
-	return (struct llc_station_state_ev *)skb->cb;
-}
-
 typedef int (*llc_station_ev_t)(struct sk_buff *skb);
 
-#define LLC_STATION_STATE_DOWN		1	/* initial state */
-#define LLC_STATION_STATE_DUP_ADDR_CHK	2
-#define LLC_STATION_STATE_UP		3
-
-#define LLC_NBR_STATION_STATES		3	/* size of state table */
-
 typedef int (*llc_station_action_t)(struct sk_buff *skb);
 
 /* Station component state table structure */
 struct llc_station_state_trans {
 	llc_station_ev_t ev;
-	u8 next_state;
 	llc_station_action_t *ev_actions;
 };
 
-struct llc_station_state {
-	u8 curr_state;
-	struct llc_station_state_trans **transitions;
-};
-
 static struct llc_station llc_main_station;
 
-static int llc_stat_ev_enable_with_dup_addr_check(struct sk_buff *skb)
-{
-	struct llc_station_state_ev *ev = llc_station_ev(skb);
-
-	return ev->type == LLC_STATION_EV_TYPE_SIMPLE &&
-	       ev->prim_type ==
-			      LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK ? 0 : 1;
-}
-
-static int llc_stat_ev_enable_without_dup_addr_check(struct sk_buff *skb)
-{
-	struct llc_station_state_ev *ev = llc_station_ev(skb);
-
-	return ev->type == LLC_STATION_EV_TYPE_SIMPLE &&
-	       ev->prim_type ==
-			LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK ? 0 : 1;
-}
-
-static int llc_stat_ev_ack_tmr_exp_lt_retry_cnt_max_retry(struct sk_buff *skb)
-{
-	struct llc_station_state_ev *ev = llc_station_ev(skb);
-
-	return ev->type == LLC_STATION_EV_TYPE_ACK_TMR &&
-		llc_main_station.retry_count <
-		llc_main_station.maximum_retry ? 0 : 1;
-}
-
-static int llc_stat_ev_ack_tmr_exp_eq_retry_cnt_max_retry(struct sk_buff *skb)
-{
-	struct llc_station_state_ev *ev = llc_station_ev(skb);
-
-	return ev->type == LLC_STATION_EV_TYPE_ACK_TMR &&
-		llc_main_station.retry_count ==
-		llc_main_station.maximum_retry ? 0 : 1;
-}
-
 static int llc_stat_ev_rx_null_dsap_xid_c(struct sk_buff *skb)
 {
-	struct llc_station_state_ev *ev = llc_station_ev(skb);
 	struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
 
-	return ev->type == LLC_STATION_EV_TYPE_PDU &&
-	       LLC_PDU_IS_CMD(pdu) &&			/* command PDU */
+	return LLC_PDU_IS_CMD(pdu) &&			/* command PDU */
 	       LLC_PDU_TYPE_IS_U(pdu) &&		/* U type PDU */
 	       LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_XID &&
 	       !pdu->dsap ? 0 : 1;			/* NULL DSAP value */
 }
 
-static int llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq(struct sk_buff *skb)
-{
-	struct llc_station_state_ev *ev = llc_station_ev(skb);
-	struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
-
-	return ev->type == LLC_STATION_EV_TYPE_PDU &&
-	       LLC_PDU_IS_RSP(pdu) &&			/* response PDU */
-	       LLC_PDU_TYPE_IS_U(pdu) &&		/* U type PDU */
-	       LLC_U_PDU_RSP(pdu) == LLC_1_PDU_CMD_XID &&
-	       !pdu->dsap &&				/* NULL DSAP value */
-	       !llc_main_station.xid_r_count ? 0 : 1;
-}
-
-static int llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq(struct sk_buff *skb)
-{
-	struct llc_station_state_ev *ev = llc_station_ev(skb);
-	struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
-
-	return ev->type == LLC_STATION_EV_TYPE_PDU &&
-	       LLC_PDU_IS_RSP(pdu) &&			/* response PDU */
-	       LLC_PDU_TYPE_IS_U(pdu) &&		/* U type PDU */
-	       LLC_U_PDU_RSP(pdu) == LLC_1_PDU_CMD_XID &&
-	       !pdu->dsap &&				/* NULL DSAP value */
-	       llc_main_station.xid_r_count == 1 ? 0 : 1;
-}
-
 static int llc_stat_ev_rx_null_dsap_test_c(struct sk_buff *skb)
 {
-	struct llc_station_state_ev *ev = llc_station_ev(skb);
 	struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
 
-	return ev->type == LLC_STATION_EV_TYPE_PDU &&
-	       LLC_PDU_IS_CMD(pdu) &&			/* command PDU */
+	return LLC_PDU_IS_CMD(pdu) &&			/* command PDU */
 	       LLC_PDU_TYPE_IS_U(pdu) &&		/* U type PDU */
 	       LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_TEST &&
 	       !pdu->dsap ? 0 : 1;			/* NULL DSAP */
 }
 
-static int llc_stat_ev_disable_req(struct sk_buff *skb)
-{
-	struct llc_station_state_ev *ev = llc_station_ev(skb);
-
-	return ev->type == LLC_STATION_EV_TYPE_PRIM &&
-	       ev->prim == LLC_DISABLE_PRIM &&
-	       ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
-}
-
 /**
  *	llc_station_send_pdu - queues PDU to send
  *	@skb: Address of the PDU
@@ -220,58 +89,6 @@ static void llc_station_send_pdu(struct sk_buff *skb)
 			break;
 }
 
-static int llc_station_ac_start_ack_timer(struct sk_buff *skb)
-{
-	mod_timer(&llc_main_station.ack_timer,
-		  jiffies + sysctl_llc_station_ack_timeout);
-	return 0;
-}
-
-static int llc_station_ac_set_retry_cnt_0(struct sk_buff *skb)
-{
-	llc_main_station.retry_count = 0;
-	return 0;
-}
-
-static int llc_station_ac_inc_retry_cnt_by_1(struct sk_buff *skb)
-{
-	llc_main_station.retry_count++;
-	return 0;
-}
-
-static int llc_station_ac_set_xid_r_cnt_0(struct sk_buff *skb)
-{
-	llc_main_station.xid_r_count = 0;
-	return 0;
-}
-
-static int llc_station_ac_inc_xid_r_cnt_by_1(struct sk_buff *skb)
-{
-	llc_main_station.xid_r_count++;
-	return 0;
-}
-
-static int llc_station_ac_send_null_dsap_xid_c(struct sk_buff *skb)
-{
-	int rc = 1;
-	struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U,
-					       sizeof(struct llc_xid_info));
-
-	if (!nskb)
-		goto out;
-	llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, 0, LLC_PDU_CMD);
-	llc_pdu_init_as_xid_cmd(nskb, LLC_XID_NULL_CLASS_2, 127);
-	rc = llc_mac_hdr_init(nskb, skb->dev->dev_addr, skb->dev->dev_addr);
-	if (unlikely(rc))
-		goto free;
-	llc_station_send_pdu(nskb);
-out:
-	return rc;
-free:
-	kfree_skb(nskb);
-	goto out;
-}
-
 static int llc_station_ac_send_xid_r(struct sk_buff *skb)
 {
 	u8 mac_da[ETH_ALEN], dsap;
@@ -326,60 +143,6 @@ free:
 	goto out;
 }
 
-static int llc_station_ac_report_status(struct sk_buff *skb)
-{
-	return 0;
-}
-
-/* DOWN STATE transitions */
-
-/* state transition for LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK event */
-static llc_station_action_t llc_stat_down_state_actions_1[] = {
-	[0] = llc_station_ac_start_ack_timer,
-	[1] = llc_station_ac_set_retry_cnt_0,
-	[2] = llc_station_ac_set_xid_r_cnt_0,
-	[3] = llc_station_ac_send_null_dsap_xid_c,
-	[4] = NULL,
-};
-
-static struct llc_station_state_trans llc_stat_down_state_trans_1 = {
-	.ev	    = llc_stat_ev_enable_with_dup_addr_check,
-	.next_state = LLC_STATION_STATE_DUP_ADDR_CHK,
-	.ev_actions = llc_stat_down_state_actions_1,
-};
-
-/* state transition for LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK event */
-static llc_station_action_t llc_stat_down_state_actions_2[] = {
-	[0] = llc_station_ac_report_status,	/* STATION UP */
-	[1] = NULL,
-};
-
-static struct llc_station_state_trans llc_stat_down_state_trans_2 = {
-	.ev	    = llc_stat_ev_enable_without_dup_addr_check,
-	.next_state = LLC_STATION_STATE_UP,
-	.ev_actions = llc_stat_down_state_actions_2,
-};
-
-/* array of pointers; one to each transition */
-static struct llc_station_state_trans *llc_stat_dwn_state_trans[] = {
-	[0] = &llc_stat_down_state_trans_1,
-	[1] = &llc_stat_down_state_trans_2,
-	[2] = NULL,
-};
-
-/* UP STATE transitions */
-/* state transition for LLC_STATION_EV_DISABLE_REQ event */
-static llc_station_action_t llc_stat_up_state_actions_1[] = {
-	[0] = llc_station_ac_report_status,	/* STATION DOWN */
-	[1] = NULL,
-};
-
-static struct llc_station_state_trans llc_stat_up_state_trans_1 = {
-	.ev	    = llc_stat_ev_disable_req,
-	.next_state = LLC_STATION_STATE_DOWN,
-	.ev_actions = llc_stat_up_state_actions_1,
-};
-
 /* state transition for LLC_STATION_EV_RX_NULL_DSAP_XID_C event */
 static llc_station_action_t llc_stat_up_state_actions_2[] = {
 	[0] = llc_station_ac_send_xid_r,
@@ -388,7 +151,6 @@ static llc_station_action_t llc_stat_up_state_actions_2[] = {
 
 static struct llc_station_state_trans llc_stat_up_state_trans_2 = {
 	.ev	    = llc_stat_ev_rx_null_dsap_xid_c,
-	.next_state = LLC_STATION_STATE_UP,
 	.ev_actions = llc_stat_up_state_actions_2,
 };
 
@@ -400,127 +162,14 @@ static llc_station_action_t llc_stat_up_state_actions_3[] = {
 
 static struct llc_station_state_trans llc_stat_up_state_trans_3 = {
 	.ev	    = llc_stat_ev_rx_null_dsap_test_c,
-	.next_state = LLC_STATION_STATE_UP,
 	.ev_actions = llc_stat_up_state_actions_3,
 };
 
 /* array of pointers; one to each transition */
 static struct llc_station_state_trans *llc_stat_up_state_trans [] = {
-	[0] = &llc_stat_up_state_trans_1,
-	[1] = &llc_stat_up_state_trans_2,
-	[2] = &llc_stat_up_state_trans_3,
-	[3] = NULL,
-};
-
-/* DUP ADDR CHK STATE transitions */
-/* state transition for LLC_STATION_EV_RX_NULL_DSAP_0_XID_R_XID_R_CNT_EQ
- * event
- */
-static llc_station_action_t llc_stat_dupaddr_state_actions_1[] = {
-	[0] = llc_station_ac_inc_xid_r_cnt_by_1,
-	[1] = NULL,
-};
-
-static struct llc_station_state_trans llc_stat_dupaddr_state_trans_1 = {
-	.ev	    = llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq,
-	.next_state = LLC_STATION_STATE_DUP_ADDR_CHK,
-	.ev_actions = llc_stat_dupaddr_state_actions_1,
-};
-
-/* state transition for LLC_STATION_EV_RX_NULL_DSAP_1_XID_R_XID_R_CNT_EQ
- * event
- */
-static llc_station_action_t llc_stat_dupaddr_state_actions_2[] = {
-	[0] = llc_station_ac_report_status,	/* DUPLICATE ADDRESS FOUND */
-	[1] = NULL,
-};
-
-static struct llc_station_state_trans llc_stat_dupaddr_state_trans_2 = {
-	.ev	    = llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq,
-	.next_state = LLC_STATION_STATE_DOWN,
-	.ev_actions = llc_stat_dupaddr_state_actions_2,
-};
-
-/* state transition for LLC_STATION_EV_RX_NULL_DSAP_XID_C event */
-static llc_station_action_t llc_stat_dupaddr_state_actions_3[] = {
-	[0] = llc_station_ac_send_xid_r,
-	[1] = NULL,
-};
-
-static struct llc_station_state_trans llc_stat_dupaddr_state_trans_3 = {
-	.ev	    = llc_stat_ev_rx_null_dsap_xid_c,
-	.next_state = LLC_STATION_STATE_DUP_ADDR_CHK,
-	.ev_actions = llc_stat_dupaddr_state_actions_3,
-};
-
-/* state transition for LLC_STATION_EV_ACK_TMR_EXP_LT_RETRY_CNT_MAX_RETRY
- * event
- */
-static llc_station_action_t llc_stat_dupaddr_state_actions_4[] = {
-	[0] = llc_station_ac_start_ack_timer,
-	[1] = llc_station_ac_inc_retry_cnt_by_1,
-	[2] = llc_station_ac_set_xid_r_cnt_0,
-	[3] = llc_station_ac_send_null_dsap_xid_c,
-	[4] = NULL,
-};
-
-static struct llc_station_state_trans llc_stat_dupaddr_state_trans_4 = {
-	.ev	    = llc_stat_ev_ack_tmr_exp_lt_retry_cnt_max_retry,
-	.next_state = LLC_STATION_STATE_DUP_ADDR_CHK,
-	.ev_actions = llc_stat_dupaddr_state_actions_4,
-};
-
-/* state transition for LLC_STATION_EV_ACK_TMR_EXP_EQ_RETRY_CNT_MAX_RETRY
- * event
- */
-static llc_station_action_t llc_stat_dupaddr_state_actions_5[] = {
-	[0] = llc_station_ac_report_status,	/* STATION UP */
-	[1] = NULL,
-};
-
-static struct llc_station_state_trans llc_stat_dupaddr_state_trans_5 = {
-	.ev	    = llc_stat_ev_ack_tmr_exp_eq_retry_cnt_max_retry,
-	.next_state = LLC_STATION_STATE_UP,
-	.ev_actions = llc_stat_dupaddr_state_actions_5,
-};
-
-/* state transition for LLC_STATION_EV_DISABLE_REQ event */
-static llc_station_action_t llc_stat_dupaddr_state_actions_6[] = {
-	[0] = llc_station_ac_report_status,	/* STATION DOWN */
-	[1] = NULL,
-};
-
-static struct llc_station_state_trans llc_stat_dupaddr_state_trans_6 = {
-	.ev	    = llc_stat_ev_disable_req,
-	.next_state = LLC_STATION_STATE_DOWN,
-	.ev_actions = llc_stat_dupaddr_state_actions_6,
-};
-
-/* array of pointers; one to each transition */
-static struct llc_station_state_trans *llc_stat_dupaddr_state_trans[] = {
-	[0] = &llc_stat_dupaddr_state_trans_6,	/* Request */
-	[1] = &llc_stat_dupaddr_state_trans_4,	/* Timer */
-	[2] = &llc_stat_dupaddr_state_trans_5,
-	[3] = &llc_stat_dupaddr_state_trans_1,	/* Receive frame */
-	[4] = &llc_stat_dupaddr_state_trans_2,
-	[5] = &llc_stat_dupaddr_state_trans_3,
-	[6] = NULL,
-};
-
-static struct llc_station_state
-			llc_station_state_table[LLC_NBR_STATION_STATES] = {
-	[LLC_STATION_STATE_DOWN - 1] = {
-		.curr_state  = LLC_STATION_STATE_DOWN,
-		.transitions = llc_stat_dwn_state_trans,
-	},
-	[LLC_STATION_STATE_DUP_ADDR_CHK - 1] = {
-		.curr_state  = LLC_STATION_STATE_DUP_ADDR_CHK,
-		.transitions = llc_stat_dupaddr_state_trans,
-	},
-	[LLC_STATION_STATE_UP - 1] = {
-		.curr_state  = LLC_STATION_STATE_UP,
-		.transitions = llc_stat_up_state_trans,
-	},
+	&llc_stat_up_state_trans_2,
+	&llc_stat_up_state_trans_3,
+	NULL,
 };
 
 /**
@@ -557,10 +206,8 @@ static struct llc_station_state_trans *
 	int i = 0;
 	struct llc_station_state_trans *rc = NULL;
 	struct llc_station_state_trans **next_trans;
-	struct llc_station_state *curr_state =
-				&llc_station_state_table[llc_main_station.state - 1];
 
-	for (next_trans = curr_state->transitions; next_trans[i]; i++)
+	for (next_trans = llc_stat_up_state_trans; next_trans[i]; i++)
 		if (!next_trans[i]->ev(skb)) {
 			rc = next_trans[i];
 			break;
@@ -576,10 +223,7 @@ static struct llc_station_state_trans *
  */
 static void llc_station_free_ev(struct sk_buff *skb)
 {
-	struct llc_station_state_ev *ev = llc_station_ev(skb);
-
-	if (ev->type == LLC_STATION_EV_TYPE_PDU)
-		kfree_skb(skb);
+	kfree_skb(skb);
 }
 
 /**
@@ -594,26 +238,18 @@ static u16 llc_station_next_state(struct sk_buff *skb)
 	u16 rc = 1;
 	struct llc_station_state_trans *trans;
 
-	if (llc_main_station.state > LLC_NBR_STATION_STATES)
-		goto out;
 	trans = llc_find_station_trans(skb);
-	if (trans) {
+	if (trans)
 		/* got the state to which we next transition; perform the
 		 * actions associated with this transition before actually
 		 * transitioning to the next state
 		 */
 		rc = llc_exec_station_trans_actions(trans, skb);
-		if (!rc)
-			/* transition station to next state if all actions
-			 * execute successfully; done; wait for next event
-			 */
-			llc_main_station.state = trans->next_state;
-	} else
+	else
 		/* event not recognized in current state; re-queue it for
 		 * processing again at a later time; return failure
 		 */
 		rc = 0;
-out:
 	llc_station_free_ev(skb);
 	return rc;
 }
@@ -652,18 +288,6 @@ static void llc_station_state_process(struct sk_buff *skb)
 	spin_unlock_bh(&llc_main_station.ev_q.lock);
 }
 
-static void llc_station_ack_tmr_cb(unsigned long timeout_data)
-{
-	struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
-
-	if (skb) {
-		struct llc_station_state_ev *ev = llc_station_ev(skb);
-
-		ev->type = LLC_STATION_EV_TYPE_ACK_TMR;
-		llc_station_state_process(skb);
-	}
-}
-
 /**
  *	llc_station_rcv - send received pdu to the station state machine
  *	@skb: received frame.
@@ -672,10 +296,6 @@ static void llc_station_ack_tmr_cb(unsigned long timeout_data)
  */
 static void llc_station_rcv(struct sk_buff *skb)
 {
-	struct llc_station_state_ev *ev = llc_station_ev(skb);
-
-	ev->type   = LLC_STATION_EV_TYPE_PDU;
-	ev->reason = 0;
 	llc_station_state_process(skb);
 }
 
@@ -684,12 +304,6 @@ void __init llc_station_init(void)
 	skb_queue_head_init(&llc_main_station.mac_pdu_q);
 	skb_queue_head_init(&llc_main_station.ev_q.list);
 	spin_lock_init(&llc_main_station.ev_q.lock);
-	setup_timer(&llc_main_station.ack_timer, llc_station_ack_tmr_cb,
-			(unsigned long)&llc_main_station);
-	llc_main_station.ack_timer.expires  = jiffies +
-						sysctl_llc_station_ack_timeout;
-	llc_main_station.maximum_retry	= 1;
-	llc_main_station.state		= LLC_STATION_STATE_UP;
 	llc_set_station_handler(llc_station_rcv);
 }
 



[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply related

* [PATCH net-next 1/6] llc2: Remove pointless indirection through llc_stat_state_trans_end
From: Ben Hutchings @ 2012-09-16  3:10 UTC (permalink / raw)
  To: David S. Miller, Arnaldo Carvalho de Melo; +Cc: netdev
In-Reply-To: <1347764982.13258.207.camel@deadeye.wl.decadent.org.uk>

[-- Attachment #1: Type: text/plain, Size: 2131 bytes --]

Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 net/llc/llc_station.c |   16 ++++------------
 1 file changed, 4 insertions(+), 12 deletions(-)

diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c
index b2f2bac..e16c1b9 100644
--- a/net/llc/llc_station.c
+++ b/net/llc/llc_station.c
@@ -331,14 +331,6 @@ static int llc_station_ac_report_status(struct sk_buff *skb)
 	return 0;
 }
 
-/* COMMON STATION STATE transitions */
-
-/* dummy last-transition indicator; common to all state transition groups
- * last entry for this state
- * all members are zeros, .bss zeroes it
- */
-static struct llc_station_state_trans llc_stat_state_trans_end;
-
 /* DOWN STATE transitions */
 
 /* state transition for LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK event */
@@ -372,7 +364,7 @@ static struct llc_station_state_trans llc_stat_down_state_trans_2 = {
 static struct llc_station_state_trans *llc_stat_dwn_state_trans[] = {
 	[0] = &llc_stat_down_state_trans_1,
 	[1] = &llc_stat_down_state_trans_2,
-	[2] = &llc_stat_state_trans_end,
+	[2] = NULL,
 };
 
 /* UP STATE transitions */
@@ -417,7 +409,7 @@ static struct llc_station_state_trans *llc_stat_up_state_trans [] = {
 	[0] = &llc_stat_up_state_trans_1,
 	[1] = &llc_stat_up_state_trans_2,
 	[2] = &llc_stat_up_state_trans_3,
-	[3] = &llc_stat_state_trans_end,
+	[3] = NULL,
 };
 
 /* DUP ADDR CHK STATE transitions */
@@ -512,7 +504,7 @@ static struct llc_station_state_trans *llc_stat_dupaddr_state_trans[] = {
 	[3] = &llc_stat_dupaddr_state_trans_1,	/* Receive frame */
 	[4] = &llc_stat_dupaddr_state_trans_2,
 	[5] = &llc_stat_dupaddr_state_trans_3,
-	[6] = &llc_stat_state_trans_end,
+	[6] = NULL,
 };
 
 static struct llc_station_state
@@ -568,7 +560,7 @@ static struct llc_station_state_trans *
 	struct llc_station_state *curr_state =
 				&llc_station_state_table[llc_main_station.state - 1];
 
-	for (next_trans = curr_state->transitions; next_trans[i]->ev; i++)
+	for (next_trans = curr_state->transitions; next_trans[i]; i++)
 		if (!next_trans[i]->ev(skb)) {
 			rc = next_trans[i];
 			break;



[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply related

* [PATCH 0/6] llc2: Simplify llc_station
From: Ben Hutchings @ 2012-09-16  3:09 UTC (permalink / raw)
  To: David S. Miller, Arnaldo Carvalho de Melo; +Cc: netdev

[-- Attachment #1: Type: text/plain, Size: 742 bytes --]

There seem to have been some grand plans for llc_station, but as they
haven't been fulfilled it's just unnecessarily complicated.

Ben.

Ben Hutchings (6):
  llc2: Remove pointless indirection through llc_stat_state_trans_end
  llc2: Remove dead code for state machine
  llc2: Collapse the station event receive path
  llc2: Remove the station send queue
  llc2: Remove explicit indexing of state action arrays
  llc2: Collapse remainder of state machine into simple if-else
    if-statement

 net/llc/llc_station.c |  600 +------------------------------------------------
 1 file changed, 9 insertions(+), 591 deletions(-)


-- 
Ben Hutchings
Experience is what causes a person to make new mistakes instead of old ones.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply

* Re: [net] e1000: Small packets may get corrupted during padding by HW
From: John Fastabend @ 2012-09-16  2:30 UTC (permalink / raw)
  To: Dave, Tushar N
  Cc: Michal Miroslaw, Kirsher, Jeffrey T, davem@davemloft.net,
	netdev@vger.kernel.org, gospo@redhat.com, sassmann@redhat.com
In-Reply-To: <50552FF1.5030708@intel.com>

On 9/15/2012 6:48 PM, John Fastabend wrote:
> On 9/15/2012 6:25 PM, Dave, Tushar N wrote:
>>> -----Original Message-----
>>> From: Michał Mirosław [mailto:mirqus@gmail.com]
>>> Sent: Saturday, September 15, 2012 1:45 PM
>>> To: Kirsher, Jeffrey T
>>> Cc: davem@davemloft.net; Dave, Tushar N; netdev@vger.kernel.org;
>>> gospo@redhat.com; sassmann@redhat.com
>>> Subject: Re: [net] e1000: Small packets may get corrupted during padding
>>> by HW
>>>
>>> 2012/9/15 Jeff Kirsher <jeffrey.t.kirsher@intel.com>:
>>>> From: Tushar Dave <tushar.n.dave@intel.com>
>>>>
>>>> On PCI/PCI-X HW, if packet size is less than ETH_ZLEN, packets may get
>>>> corrupted during padding by HW.
>>>> To WA this issue, pad all small packets manually.
>>>>
>>>> Signed-off-by: Tushar Dave <tushar.n.dave@intel.com>
>>>> Tested-by: Aaron Brown <aaron.f.brown@intel.com>
>>>> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
>>>> ---
>>>>   drivers/net/ethernet/intel/e1000/e1000_main.c | 11 +++++++++++
>>>>   1 file changed, 11 insertions(+)
>>>>
>>>> diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c
>>>> b/drivers/net/ethernet/intel/e1000/e1000_main.c
>>>> index 3bfbb8d..bde337e 100644
>>>> --- a/drivers/net/ethernet/intel/e1000/e1000_main.c
>>>> +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
>>>> @@ -3149,6 +3149,17 @@ static netdev_tx_t e1000_xmit_frame(struct
>>> sk_buff *skb,
>>>>                  return NETDEV_TX_OK;
>>>>          }
>>>>
>>>> +       /* On PCI/PCI-X HW, if packet size is less than ETH_ZLEN,
>>>> +        * packets may get corrupted during padding by HW.
>>>> +        * To WA this issue, pad all small packets manually.
>>>> +        */
>>>> +       if (skb->len < ETH_ZLEN) {
>>>> +               if (skb_pad(skb, ETH_ZLEN - skb->len))
>>>> +                       return NETDEV_TX_OK;
>>>> +               skb->len = ETH_ZLEN;
>>>> +               skb_set_tail_pointer(skb, ETH_ZLEN);
>>>> +       }
>>>> +
>>>
>>> Isn't there a skb_padto() that does just this?
>>
>> Skb_padto calls skb_pad(). Calling skb_pad directly saves some cycles.
>>
>
> How/where?
>

OK maybe you avoid an if case.

^ permalink raw reply

* [PATCH] fix ZOMBIE state bug in PPPOE driver
From: Xiaodong Xu @ 2012-09-16  2:30 UTC (permalink / raw)
  To: linux-kernel; +Cc: netdev
In-Reply-To: <CANEcBPSEamgOiGqNUSwB+hYCo1k2OTXDA=qsrw0Co8_F7treWw@mail.gmail.com>

Hi All,

I found a bug in kernel PPPOE driver.
When PPPOE is running over a virtual ethernet interface (e.g., a
bonding interface) and the user tries to delete the interface in case
the PPPOE state is ZOMBIE, the kernel will loop infinitely while
unregistering net_device for the reference count is not reset to zero
which should be done by dev_put().

The following patch could fix this issue:

$ git diff
diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
index cbf7047..20f31d0 100644
--- a/drivers/net/ppp/pppoe.c
+++ b/drivers/net/ppp/pppoe.c
@@ -570,7 +570,7 @@ static int pppoe_release(struct socket *sock)

        po = pppox_sk(sk);

-       if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) {
+       if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
                dev_put(po->pppoe_dev);
                po->pppoe_dev = NULL;
        }

Thanks.

Regards,
Xiaodong Xu

^ permalink raw reply related

* Re: [net] e1000: Small packets may get corrupted during padding by HW
From: John Fastabend @ 2012-09-16  1:48 UTC (permalink / raw)
  To: Dave, Tushar N
  Cc: Michal Miroslaw, Kirsher, Jeffrey T, davem@davemloft.net,
	netdev@vger.kernel.org, gospo@redhat.com, sassmann@redhat.com
In-Reply-To: <061C8A8601E8EE4CA8D8FD6990CEA89130DC20AA@ORSMSX102.amr.corp.intel.com>

On 9/15/2012 6:25 PM, Dave, Tushar N wrote:
>> -----Original Message-----
>> From: Michał Mirosław [mailto:mirqus@gmail.com]
>> Sent: Saturday, September 15, 2012 1:45 PM
>> To: Kirsher, Jeffrey T
>> Cc: davem@davemloft.net; Dave, Tushar N; netdev@vger.kernel.org;
>> gospo@redhat.com; sassmann@redhat.com
>> Subject: Re: [net] e1000: Small packets may get corrupted during padding
>> by HW
>>
>> 2012/9/15 Jeff Kirsher <jeffrey.t.kirsher@intel.com>:
>>> From: Tushar Dave <tushar.n.dave@intel.com>
>>>
>>> On PCI/PCI-X HW, if packet size is less than ETH_ZLEN, packets may get
>>> corrupted during padding by HW.
>>> To WA this issue, pad all small packets manually.
>>>
>>> Signed-off-by: Tushar Dave <tushar.n.dave@intel.com>
>>> Tested-by: Aaron Brown <aaron.f.brown@intel.com>
>>> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
>>> ---
>>>   drivers/net/ethernet/intel/e1000/e1000_main.c | 11 +++++++++++
>>>   1 file changed, 11 insertions(+)
>>>
>>> diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c
>>> b/drivers/net/ethernet/intel/e1000/e1000_main.c
>>> index 3bfbb8d..bde337e 100644
>>> --- a/drivers/net/ethernet/intel/e1000/e1000_main.c
>>> +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
>>> @@ -3149,6 +3149,17 @@ static netdev_tx_t e1000_xmit_frame(struct
>> sk_buff *skb,
>>>                  return NETDEV_TX_OK;
>>>          }
>>>
>>> +       /* On PCI/PCI-X HW, if packet size is less than ETH_ZLEN,
>>> +        * packets may get corrupted during padding by HW.
>>> +        * To WA this issue, pad all small packets manually.
>>> +        */
>>> +       if (skb->len < ETH_ZLEN) {
>>> +               if (skb_pad(skb, ETH_ZLEN - skb->len))
>>> +                       return NETDEV_TX_OK;
>>> +               skb->len = ETH_ZLEN;
>>> +               skb_set_tail_pointer(skb, ETH_ZLEN);
>>> +       }
>>> +
>>
>> Isn't there a skb_padto() that does just this?
>
> Skb_padto calls skb_pad(). Calling skb_pad directly saves some cycles.
>

How/where?

static inline int skb_padto(struct sk_buff *skb, unsigned int len)
{
         unsigned int size = skb->len;
         if (likely(size >= len))
                 return 0;
         return skb_pad(skb, len - size);
}


Also wouldn't you want an unlikely() in your patch?

.John

^ permalink raw reply

* RE: [net] e1000: Small packets may get corrupted during padding by HW
From: Dave, Tushar N @ 2012-09-16  1:25 UTC (permalink / raw)
  To: Michal Miroslaw, Kirsher, Jeffrey T
  Cc: davem@davemloft.net, netdev@vger.kernel.org, gospo@redhat.com,
	sassmann@redhat.com
In-Reply-To: <CAHXqBFJZnGUSUutN=L-_LpCN7dXLPFY0ndJnQJ10NCcbzPVLww@mail.gmail.com>

>-----Original Message-----
>From: Michał Mirosław [mailto:mirqus@gmail.com]
>Sent: Saturday, September 15, 2012 1:45 PM
>To: Kirsher, Jeffrey T
>Cc: davem@davemloft.net; Dave, Tushar N; netdev@vger.kernel.org;
>gospo@redhat.com; sassmann@redhat.com
>Subject: Re: [net] e1000: Small packets may get corrupted during padding
>by HW
>
>2012/9/15 Jeff Kirsher <jeffrey.t.kirsher@intel.com>:
>> From: Tushar Dave <tushar.n.dave@intel.com>
>>
>> On PCI/PCI-X HW, if packet size is less than ETH_ZLEN, packets may get
>> corrupted during padding by HW.
>> To WA this issue, pad all small packets manually.
>>
>> Signed-off-by: Tushar Dave <tushar.n.dave@intel.com>
>> Tested-by: Aaron Brown <aaron.f.brown@intel.com>
>> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
>> ---
>>  drivers/net/ethernet/intel/e1000/e1000_main.c | 11 +++++++++++
>>  1 file changed, 11 insertions(+)
>>
>> diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c
>> b/drivers/net/ethernet/intel/e1000/e1000_main.c
>> index 3bfbb8d..bde337e 100644
>> --- a/drivers/net/ethernet/intel/e1000/e1000_main.c
>> +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
>> @@ -3149,6 +3149,17 @@ static netdev_tx_t e1000_xmit_frame(struct
>sk_buff *skb,
>>                 return NETDEV_TX_OK;
>>         }
>>
>> +       /* On PCI/PCI-X HW, if packet size is less than ETH_ZLEN,
>> +        * packets may get corrupted during padding by HW.
>> +        * To WA this issue, pad all small packets manually.
>> +        */
>> +       if (skb->len < ETH_ZLEN) {
>> +               if (skb_pad(skb, ETH_ZLEN - skb->len))
>> +                       return NETDEV_TX_OK;
>> +               skb->len = ETH_ZLEN;
>> +               skb_set_tail_pointer(skb, ETH_ZLEN);
>> +       }
>> +
>
>Isn't there a skb_padto() that does just this?

Skb_padto calls skb_pad(). Calling skb_pad directly saves some cycles.

^ permalink raw reply

* Uppgradera ditt e-postkonto
From: E-post administratör @ 2012-09-14  8:11 UTC (permalink / raw)
  To: info; +Cc: info

Kära e-postanvändare,
 
Din webbmail kvot har överskridit den fastställda kvoten som är 3GB. du
för närvarande kör på 3.9GB.
För att åter aktivera och öka din webbmail kvot Klicka på länken
nedan:
 
https://docs.google.com/spreadsheet/viewform?formkey=dHkwbU1HTU1EcUVrM25YZHJweFlqUkE6MQ
  
Underlåtenhet att göra detta kan resultera i uppsägning av din webbmail
konto.
Tack, och ber om ursäkt för besväret
Localhost.

^ permalink raw reply

* Re: [net] e1000: Small packets may get corrupted during padding by HW
From: Michał Mirosław @ 2012-09-15 20:44 UTC (permalink / raw)
  To: Jeff Kirsher; +Cc: davem, Tushar Dave, netdev, gospo, sassmann
In-Reply-To: <1347740217-10257-1-git-send-email-jeffrey.t.kirsher@intel.com>

2012/9/15 Jeff Kirsher <jeffrey.t.kirsher@intel.com>:
> From: Tushar Dave <tushar.n.dave@intel.com>
>
> On PCI/PCI-X HW, if packet size is less than ETH_ZLEN,
> packets may get corrupted during padding by HW.
> To WA this issue, pad all small packets manually.
>
> Signed-off-by: Tushar Dave <tushar.n.dave@intel.com>
> Tested-by: Aaron Brown <aaron.f.brown@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
> ---
>  drivers/net/ethernet/intel/e1000/e1000_main.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
>
> diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
> index 3bfbb8d..bde337e 100644
> --- a/drivers/net/ethernet/intel/e1000/e1000_main.c
> +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
> @@ -3149,6 +3149,17 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
>                 return NETDEV_TX_OK;
>         }
>
> +       /* On PCI/PCI-X HW, if packet size is less than ETH_ZLEN,
> +        * packets may get corrupted during padding by HW.
> +        * To WA this issue, pad all small packets manually.
> +        */
> +       if (skb->len < ETH_ZLEN) {
> +               if (skb_pad(skb, ETH_ZLEN - skb->len))
> +                       return NETDEV_TX_OK;
> +               skb->len = ETH_ZLEN;
> +               skb_set_tail_pointer(skb, ETH_ZLEN);
> +       }
> +

Isn't there a skb_padto() that does just this?

Best Regards,
Michał Mirosław

^ permalink raw reply

* [net] e1000: Small packets may get corrupted during padding by HW
From: Jeff Kirsher @ 2012-09-15 20:16 UTC (permalink / raw)
  To: davem; +Cc: Tushar Dave, netdev, gospo, sassmann, Jeff Kirsher

From: Tushar Dave <tushar.n.dave@intel.com>

On PCI/PCI-X HW, if packet size is less than ETH_ZLEN,
packets may get corrupted during padding by HW.
To WA this issue, pad all small packets manually.

Signed-off-by: Tushar Dave <tushar.n.dave@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/e1000/e1000_main.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index 3bfbb8d..bde337e 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -3149,6 +3149,17 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
 		return NETDEV_TX_OK;
 	}
 
+	/* On PCI/PCI-X HW, if packet size is less than ETH_ZLEN,
+	 * packets may get corrupted during padding by HW.
+	 * To WA this issue, pad all small packets manually.
+	 */
+	if (skb->len < ETH_ZLEN) {
+		if (skb_pad(skb, ETH_ZLEN - skb->len))
+			return NETDEV_TX_OK;
+		skb->len = ETH_ZLEN;
+		skb_set_tail_pointer(skb, ETH_ZLEN);
+	}
+
 	mss = skb_shinfo(skb)->gso_size;
 	/* The controller does a simple calculation to
 	 * make sure there is enough room in the FIFO before
-- 
1.7.11.4

^ permalink raw reply related

* Warning! Your mailbox is almost full.
From: Webmail Account Upgrade @ 2012-09-15 17:20 UTC (permalink / raw)


You have exceeded your email limit quota of 450MB. You need to upgrade  
your email limit quota to 2GB within the next 48 hours. Use the below  
web link to upgrade your email account:

click link below:
   http://www.formchamp.com/goform.php?id=38313

Thank you for using our email.
Copyright ©2012 Email Helpdesk Centre.
----------------------------------------------------------------
This message was sent using IMP, the Internet Messaging Program.

^ permalink raw reply

* Re: kernel BUG at kernel/timer.c:748!
From: Yuchung Cheng @ 2012-09-15 18:16 UTC (permalink / raw)
  To: Dave Jones; +Cc: Julian Anastasov, netdev
In-Reply-To: <20120914212958.GA25053@redhat.com>

On Fri, Sep 14, 2012 at 2:29 PM, Dave Jones <davej@redhat.com> wrote:
> On Wed, Sep 05, 2012 at 11:48:29PM +0300, Julian Anastasov wrote:
>
>  > > kernel BUG at kernel/timer.c:748!
>  > > Call Trace:
>  > >  ? lock_sock_nested+0x8d/0xa0
>  > >  sk_reset_timer+0x1c/0x30
>  > >  ? sock_setsockopt+0x8c/0x960
>  > >  inet_csk_reset_keepalive_timer+0x20/0x30
>  > >  tcp_set_keepalive+0x3d/0x50
>  > >  sock_setsockopt+0x923/0x960
>  > >  ? trace_hardirqs_on_caller+0x16/0x1e0
>  > >  ? fget_light+0x24c/0x520
>  > >  sys_setsockopt+0xc6/0xe0
>  > >  system_call_fastpath+0x1a/0x1f
>  >
>  >      Can this help? In case you see ICMPV6_PKT_TOOBIG...
>  >
>  > [PATCH] tcp: fix possible socket refcount problem for ipv6
>
> I just managed to reproduce this bug on rc5 with this patch,
> so it doesn't seem to help.
Could you post some tcpdump traces?

>
>         Dave
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [RFC PATCH 3/3] usbnet: support runtime PM triggered by link change
From: Ming Lei @ 2012-09-15 17:48 UTC (permalink / raw)
  To: David S. Miller, Greg Kroah-Hartman
  Cc: Oliver Neukum, Fink Dmitry, Rafael Wysocki, Alan Stern, netdev,
	linux-usb, Ming Lei
In-Reply-To: <1347731299-29898-1-git-send-email-ming.lei@canonical.com>

This patch implements runtime PM triggered by link change event
for devices which haven't defined manage_power() callback, based
on the below consideration:

- this kind of runtime PM has been supported by some PCI network
interfaces already, and it does make sense to suspend the usb
device to save power if no link is detected

- link down triggered runtime needn't to be implemented for devices
which have already supported traffic based runtime PM by .manage_power,
because runtime suspend can be triggered when no tx frames are to be
transmitted after link becoms down.

Unfortunately, some usbnet devices don't support remote wakeup,
or some devices may support it but the remote wakup can't be enabled
for link change event for some reason(no documents are public, not
supported ...).

This patch takes a periodic timer to wake up devices for detecting
the link change event if remote wakeup by link change can't be
supported. If the link is found to be down, put the device into
suspend immediately.

For the devices which support remote wakeup by link change and
don't support remote wakeup by incoming packets(not implement
manage_power callback), the patch can still make link change
triggered runtime PM working on these devices.

Signed-off-by: Ming Lei <ming.lei@canonical.com>
---
 drivers/net/usb/sierra_net.c |    3 +-
 drivers/net/usb/usbnet.c     |  211 +++++++++++++++++++++++++++++++++++++++++-
 include/linux/usb/usbnet.h   |   19 ++++
 3 files changed, 229 insertions(+), 4 deletions(-)

diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c
index 08ed9e5..0993f2d 100644
--- a/drivers/net/usb/sierra_net.c
+++ b/drivers/net/usb/sierra_net.c
@@ -418,6 +418,7 @@ static void sierra_net_handle_lsi(struct usbnet *dev, char *data,
 		priv->link_up = 0;
 	}
 	usbnet_link_change(dev, link_up, 0);
+	usbnet_link_updated(dev);
 }
 
 static void sierra_net_dosync(struct usbnet *dev)
@@ -915,7 +916,7 @@ static struct sk_buff *sierra_net_tx_fixup(struct usbnet *dev,
 
 static const struct driver_info sierra_net_info_direct_ip = {
 	.description = "Sierra Wireless USB-to-WWAN Modem",
-	.flags = FLAG_WWAN | FLAG_SEND_ZLP,
+	.flags = FLAG_WWAN | FLAG_SEND_ZLP | FLAG_LINK_UPDATE_BY_DRIVER,
 	.bind = sierra_net_bind,
 	.unbind = sierra_net_unbind,
 	.status = sierra_net_status,
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 054ffd8..8db1618 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -677,6 +677,186 @@ static void usbnet_terminate_urbs(struct usbnet *dev)
 	remove_wait_queue(&unlink_wakeup, &wait);
 }
 
+void usbnet_link_updated(struct usbnet *dev)
+{
+	complete(&dev->link_update_completion);
+}
+EXPORT_SYMBOL_GPL(usbnet_link_updated);
+
+#define usbnet_link_suspend(dev) do { \
+	dev_dbg(&dev->intf->dev, "%s:link suspend", __func__); \
+	usb_autopm_put_interface_async(dev->intf); \
+} while(0)
+
+#define usbnet_link_resume(dev) do { \
+	dev_dbg(&dev->intf->dev, "%s:link resume", __func__); \
+	usb_autopm_get_interface_async(dev->intf); \
+} while(0)
+
+static int need_link_runtime_pm(struct usbnet *dev)
+{
+	if (dev->driver_info->manage_power)
+		return 0;
+
+	if (!dev->driver_info->status)
+		return 0;
+
+	return 1;
+}
+
+/* called by usbnet_suspend */
+static void start_link_detect(struct usbnet *dev)
+{
+	if (!dev->link_rpm_enabled)
+		return;
+
+	if (dev->link_remote_wakeup)
+		return;
+
+	if (dev->link_check_started)
+		return;
+
+	dev->link_check_started = 1;
+	schedule_delayed_work(&dev->link_detect_work,
+			      msecs_to_jiffies(3000));
+}
+
+/* called by usbnet_resume */
+static void end_link_detect(struct usbnet *dev, int force_cancel)
+{
+	if (!dev->link_rpm_enabled)
+		return;
+
+	if (!dev->link_check_started)
+		return;
+
+	/*
+	 * cancel the link detect work if usbnet is resumed
+	 * not by link detect work
+	 */
+	if (!dev->link_checking || force_cancel)
+		cancel_delayed_work_sync(&dev->link_detect_work);
+
+	dev->link_check_started = 0;
+}
+
+/* called by usbnet_open */
+static void enable_link_runtime_pm(struct usbnet *dev)
+{
+	dev->link_rpm_enabled = 1;
+
+	if (!dev->link_remote_wakeup) {
+		dev->old_autosuspend_delay =
+			dev->udev->dev.power.autosuspend_delay;
+		pm_runtime_set_autosuspend_delay(&dev->udev->dev, 1);
+	}
+
+	if (!netif_carrier_ok(dev->net)) {
+		dev->link_open_suspend = 1;
+		usbnet_link_suspend(dev);
+	}
+}
+
+/* called by usbnet_stop */
+static void disable_link_runtime_pm(struct usbnet *dev)
+{
+	if (!dev->link_rpm_enabled)
+		return;
+	dev->link_rpm_enabled = 0;
+	end_link_detect(dev, 1);
+	if (dev->link_open_suspend) {
+		usbnet_link_resume(dev);
+		dev->link_open_suspend = 0;
+	}
+	if (!dev->link_remote_wakeup)
+		pm_runtime_set_autosuspend_delay(&dev->udev->dev,
+						 dev->old_autosuspend_delay);
+}
+
+static void update_link_state(struct usbnet *dev)
+{
+	char		*buf = NULL;
+	unsigned	pipe = 0;
+	unsigned	maxp;
+	int		ret, act_len, timeout;
+	struct urb	urb;
+
+	pipe = usb_rcvintpipe(dev->udev,
+			      dev->status->desc.bEndpointAddress
+				& USB_ENDPOINT_NUMBER_MASK);
+	maxp = usb_maxpacket(dev->udev, pipe, 0);
+
+	/*
+	 * Take default timeout as 2 times of period.
+	 * It is observed that asix device can update its link
+	 * state duing one period(128ms). Low level driver can set
+	 * its default update link time in bind() callback.
+	 */
+	if (!dev->link_update_timeout) {
+		timeout = max((int) dev->status->desc.bInterval,
+			(dev->udev->speed == USB_SPEED_HIGH) ? 7 : 3);
+		timeout = 1 << timeout;
+		if (dev->udev->speed == USB_SPEED_HIGH)
+			timeout /= 8;
+		if (timeout < 128)
+			timeout = 128;
+	} else
+		timeout = dev->link_update_timeout;
+
+	buf = kmalloc(maxp, GFP_KERNEL);
+	if (!buf)
+		return;
+
+	dev_dbg(&dev->intf->dev, "%s: timeout %dms\n", __func__, timeout);
+	ret = usb_interrupt_msg(dev->udev, pipe, buf, maxp,
+			&act_len, timeout);
+	if (!ret) {
+		urb.status = 0;
+		urb.actual_length = act_len;
+		urb.transfer_buffer = buf;
+		urb.transfer_buffer_length = maxp;
+		dev->driver_info->status(dev, &urb);
+		if (dev->driver_info->flags &
+		    FLAG_LINK_UPDATE_BY_DRIVER)
+			wait_for_completion(&dev->link_update_completion);
+		dev_dbg(&dev->intf->dev, "%s: link updated\n", __func__);
+	} else
+		dev_dbg(&dev->intf->dev, "%s: link update failed %d\n",
+				__func__, ret);
+	kfree(buf);
+}
+
+static void link_detect_work(struct work_struct *work)
+{
+	struct usbnet	*dev = container_of(work, struct usbnet,
+					    link_detect_work.work);
+
+	dev_dbg(&dev->intf->dev, "%s: link resume\n", __func__);
+
+	dev->link_checking = 1;
+	usb_autopm_get_interface(dev->intf);
+	update_link_state(dev);
+	dev->link_checking = 0;
+
+	dev_dbg(&dev->intf->dev, "%s: link state %d\n",
+		__func__, netif_carrier_ok(dev->net));
+
+	if (!netif_carrier_ok(dev->net))
+		usb_autopm_put_interface(dev->intf);
+	else
+		usb_submit_urb(dev->interrupt, GFP_NOIO);
+}
+
+static void init_link_rpm(struct usbnet *dev)
+{
+	INIT_DELAYED_WORK(&dev->link_detect_work, link_detect_work);
+	init_completion(&dev->link_update_completion);
+
+	dev->link_remote_wakeup = !!(dev->driver_info->flags &
+				  FLAG_LINK_SUPPORT_REMOTE_WAKEUP);
+	dev->link_state = 1;
+}
+
 int usbnet_stop (struct net_device *net)
 {
 	struct usbnet		*dev = netdev_priv(net);
@@ -719,8 +899,10 @@ int usbnet_stop (struct net_device *net)
 	tasklet_kill (&dev->bh);
 	if (info->manage_power)
 		info->manage_power(dev, 0);
-	else
+	else {
+		disable_link_runtime_pm(dev);
 		usb_autopm_put_interface(dev->intf);
+	}
 
 	return 0;
 }
@@ -795,6 +977,9 @@ int usbnet_open (struct net_device *net)
 		if (retval < 0)
 			goto done_manage_power_error;
 		usb_autopm_put_interface(dev->intf);
+	} else {
+		if (need_link_runtime_pm(dev))
+			enable_link_runtime_pm(dev);
 	}
 	return retval;
 
@@ -1489,6 +1674,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
 	if (dev->driver_info->flags & FLAG_LINK_INTR)
 		usbnet_link_change(dev, 0, 0);
 
+	init_link_rpm(dev);
+
 	return 0;
 
 out4:
@@ -1538,6 +1725,9 @@ int usbnet_suspend (struct usb_interface *intf, pm_message_t message)
 		 * wake the device
 		 */
 		netif_device_attach (dev->net);
+
+		if (PMSG_IS_AUTO(message))
+			start_link_detect(dev);
 	}
 	return 0;
 }
@@ -1552,8 +1742,10 @@ int usbnet_resume (struct usb_interface *intf)
 
 	if (!--dev->suspend_count) {
 		/* resume interrupt URBs */
-		if (dev->interrupt && test_bit(EVENT_DEV_OPEN, &dev->flags))
-			usb_submit_urb(dev->interrupt, GFP_NOIO);
+		if (dev->interrupt && test_bit(EVENT_DEV_OPEN, &dev->flags)) {
+			if (!dev->link_checking)
+				usb_submit_urb(dev->interrupt, GFP_NOIO);
+		}
 
 		spin_lock_irq(&dev->txq.lock);
 		while ((res = usb_get_from_anchor(&dev->deferred))) {
@@ -1586,6 +1778,8 @@ int usbnet_resume (struct usb_interface *intf)
 				netif_tx_wake_all_queues(dev->net);
 			tasklet_schedule (&dev->bh);
 		}
+
+		end_link_detect(dev, 0);
 	}
 	return 0;
 }
@@ -1593,6 +1787,9 @@ EXPORT_SYMBOL_GPL(usbnet_resume);
 
 void usbnet_link_change(struct usbnet *dev, int link, int need_reset)
 {
+	dev_dbg(&dev->intf->dev, "%s: old_link=%d link=%d\n", __func__,
+		dev->link_state, link);
+
 	if (link)
 		netif_carrier_on(dev->net);
 	else
@@ -1600,6 +1797,14 @@ void usbnet_link_change(struct usbnet *dev, int link, int need_reset)
 
 	if (need_reset && link)
 		usbnet_defer_kevent(dev, EVENT_LINK_RESET);
+
+	if (dev->link_rpm_enabled) {
+		if (!link && dev->link_state)
+			usbnet_link_suspend(dev);
+		else if (link && !dev->link_state && dev->link_remote_wakeup)
+			usbnet_link_resume(dev);
+	}
+	dev->link_state = link;
 }
 EXPORT_SYMBOL_GPL(usbnet_link_change);
 
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index 1937b74..c96a623 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -68,6 +68,18 @@ struct usbnet {
 #		define EVENT_RX_PAUSED	5
 #		define EVENT_DEV_ASLEEP 6
 #		define EVENT_DEV_OPEN	7
+
+	/* link down triggered runtime PM */
+	struct delayed_work	link_detect_work;
+	struct completion	link_update_completion;
+	int			link_update_timeout;
+	int			old_autosuspend_delay;
+	unsigned int		link_rpm_enabled:1;
+	unsigned int		link_check_started:1;
+	unsigned int		link_checking:1;
+	unsigned int		link_open_suspend:1;
+	unsigned int		link_state:1;
+	unsigned int		link_remote_wakeup:1;
 };
 
 static inline struct usb_driver *driver_of(struct usb_interface *intf)
@@ -106,6 +118,12 @@ struct driver_info {
 #define FLAG_MULTI_PACKET	0x2000
 #define FLAG_RX_ASSEMBLE	0x4000	/* rx packets may span >1 frames */
 
+/* some drivers may not update link state in .status */
+#define FLAG_LINK_UPDATE_BY_DRIVER	0x8000
+
+/* device support remote wakeup by link change */
+#define FLAG_LINK_SUPPORT_REMOTE_WAKEUP	0x10000
+
 	/* init device ... can sleep, or cause probe() failure */
 	int	(*bind)(struct usbnet *, struct usb_interface *);
 
@@ -161,6 +179,7 @@ extern int usbnet_suspend(struct usb_interface *, pm_message_t);
 extern int usbnet_resume(struct usb_interface *);
 extern void usbnet_disconnect(struct usb_interface *);
 extern void usbnet_link_change(struct usbnet *dev, int link, int need_reset);
+extern void usbnet_link_updated(struct usbnet *dev);
 
 /* Drivers that reuse some of the standard USB CDC infrastructure
  * (notably, using multiple interfaces according to the CDC
-- 
1.7.9.5

^ permalink raw reply related

* [RFC PATCH 2/3] usbnet: apply usbnet_link_change
From: Ming Lei @ 2012-09-15 17:48 UTC (permalink / raw)
  To: David S. Miller, Greg Kroah-Hartman
  Cc: Oliver Neukum, Fink Dmitry, Rafael Wysocki, Alan Stern, netdev,
	linux-usb, Ming Lei
In-Reply-To: <1347731299-29898-1-git-send-email-ming.lei@canonical.com>

This patch applies the introduce usbnet_link_change API.

Signed-off-by: Ming Lei <ming.lei@canonical.com>
---
 drivers/net/usb/asix_devices.c |    6 +-----
 drivers/net/usb/cdc_ether.c    |    5 +----
 drivers/net/usb/cdc_ncm.c      |    9 +++------
 drivers/net/usb/dm9601.c       |    7 +------
 drivers/net/usb/mcs7830.c      |    6 +-----
 drivers/net/usb/sierra_net.c   |    3 +--
 drivers/net/usb/usbnet.c       |    2 +-
 7 files changed, 9 insertions(+), 29 deletions(-)

diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
index 4fd48df..c354bb1 100644
--- a/drivers/net/usb/asix_devices.c
+++ b/drivers/net/usb/asix_devices.c
@@ -55,11 +55,7 @@ static void asix_status(struct usbnet *dev, struct urb *urb)
 	event = urb->transfer_buffer;
 	link = event->link & 0x01;
 	if (netif_carrier_ok(dev->net) != link) {
-		if (link) {
-			netif_carrier_on(dev->net);
-			usbnet_defer_kevent (dev, EVENT_LINK_RESET );
-		} else
-			netif_carrier_off(dev->net);
+		usbnet_link_change(dev, link, 1);
 		netdev_dbg(dev->net, "Link Status is: %d\n", link);
 	}
 }
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index a03de71..c6e4be5 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -406,10 +406,7 @@ void usbnet_cdc_status(struct usbnet *dev, struct urb *urb)
 	case USB_CDC_NOTIFY_NETWORK_CONNECTION:
 		netif_dbg(dev, timer, dev->net, "CDC: carrier %s\n",
 			  event->wValue ? "on" : "off");
-		if (event->wValue)
-			netif_carrier_on(dev->net);
-		else
-			netif_carrier_off(dev->net);
+		usbnet_link_change(dev, event->wValue, 0);
 		break;
 	case USB_CDC_NOTIFY_SPEED_CHANGE:	/* tx/rx rates */
 		netif_dbg(dev, timer, dev->net, "CDC: speed change (len %d)\n",
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index 4cd582a..f425c2c 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -593,7 +593,7 @@ advance:
 	 * (carrier is OFF) during attach, so the IP network stack does not
 	 * start IPv6 negotiation and more.
 	 */
-	netif_carrier_off(dev->net);
+	usbnet_link_change(dev, 0, 0);
 	ctx->tx_speed = ctx->rx_speed = 0;
 	return 0;
 
@@ -1131,12 +1131,9 @@ static void cdc_ncm_status(struct usbnet *dev, struct urb *urb)
 			" %sconnected\n",
 			ctx->netdev->name, ctx->connected ? "" : "dis");
 
-		if (ctx->connected)
-			netif_carrier_on(dev->net);
-		else {
-			netif_carrier_off(dev->net);
+		usbnet_link_change(dev, ctx->connected, 0);
+		if (!ctx->connected)
 			ctx->tx_speed = ctx->rx_speed = 0;
-		}
 		break;
 
 	case USB_CDC_NOTIFY_SPEED_CHANGE:
diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c
index e0433ce..7422d5a 100644
--- a/drivers/net/usb/dm9601.c
+++ b/drivers/net/usb/dm9601.c
@@ -587,12 +587,7 @@ static void dm9601_status(struct usbnet *dev, struct urb *urb)
 
 	link = !!(buf[0] & 0x40);
 	if (netif_carrier_ok(dev->net) != link) {
-		if (link) {
-			netif_carrier_on(dev->net);
-			usbnet_defer_kevent (dev, EVENT_LINK_RESET);
-		}
-		else
-			netif_carrier_off(dev->net);
+		usbnet_link_change(dev, link, 1);
 		netdev_dbg(dev->net, "Link Status is: %d\n", link);
 	}
 }
diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c
index 03c2d8d..49a98b7 100644
--- a/drivers/net/usb/mcs7830.c
+++ b/drivers/net/usb/mcs7830.c
@@ -639,11 +639,7 @@ static void mcs7830_status(struct usbnet *dev, struct urb *urb)
 
 	link = !(buf[1] & 0x20);
 	if (netif_carrier_ok(dev->net) != link) {
-		if (link) {
-			netif_carrier_on(dev->net);
-			usbnet_defer_kevent(dev, EVENT_LINK_RESET);
-		} else
-			netif_carrier_off(dev->net);
+		usbnet_link_change(dev, link, 1);
 		netdev_dbg(dev->net, "Link Status is: %d\n", link);
 	}
 }
diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c
index 7ae70e9..08ed9e5 100644
--- a/drivers/net/usb/sierra_net.c
+++ b/drivers/net/usb/sierra_net.c
@@ -414,11 +414,10 @@ static void sierra_net_handle_lsi(struct usbnet *dev, char *data,
 	if (link_up) {
 		sierra_net_set_ctx_index(priv, hh->msgspecific.byte);
 		priv->link_up = 1;
-		netif_carrier_on(dev->net);
 	} else {
 		priv->link_up = 0;
-		netif_carrier_off(dev->net);
 	}
+	usbnet_link_change(dev, link_up, 0);
 }
 
 static void sierra_net_dosync(struct usbnet *dev)
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 95a96b1..054ffd8 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1487,7 +1487,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
 	netif_device_attach (net);
 
 	if (dev->driver_info->flags & FLAG_LINK_INTR)
-		netif_carrier_off(net);
+		usbnet_link_change(dev, 0, 0);
 
 	return 0;
 
-- 
1.7.9.5

^ permalink raw reply related

* [RFC PATCH 0/3] usbnet: support runtime PM triggered by link change
From: Ming Lei @ 2012-09-15 17:48 UTC (permalink / raw)
  To: David S. Miller, Greg Kroah-Hartman
  Cc: Oliver Neukum, Fink Dmitry, Rafael Wysocki, Alan Stern, netdev,
	linux-usb

Hi,

Currently only very few usbnet devices support the traffic based
runtime PM, eg. wake up devices if there are packets to be transmitted.

For the below situation, it should make sense to runtime suspend usbnet
device to save power:
	
	- after network link becomes down

This patch implements the runtime PM triggered by network link change
event, and it works basically on asix usbnet device after a simple
runtime PM test.

 drivers/net/usb/asix_devices.c |    6 +-
 drivers/net/usb/cdc_ether.c    |    5 +-
 drivers/net/usb/cdc_ncm.c      |    9 +-
 drivers/net/usb/dm9601.c       |    7 +-
 drivers/net/usb/mcs7830.c      |    6 +-
 drivers/net/usb/sierra_net.c   |    6 +-
 drivers/net/usb/usbnet.c       |  224 +++++++++++++++++++++++++++++++++++++++-
 include/linux/usb/usbnet.h     |   21 +++-
 8 files changed, 250 insertions(+), 34 deletions(-)


Thanks
--
Ming Lei

^ permalink raw reply

* [RFC PATCH 1/3] usbnet: introduce usbnet_link_change API
From: Ming Lei @ 2012-09-15 17:48 UTC (permalink / raw)
  To: David S. Miller, Greg Kroah-Hartman
  Cc: Oliver Neukum, Fink Dmitry, Rafael Wysocki, Alan Stern,
	netdev-u79uwXL29TY76Z2rM5mHXA, linux-usb-u79uwXL29TY76Z2rM5mHXA,
	Ming Lei
In-Reply-To: <1347731299-29898-1-git-send-email-ming.lei-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>

This patch introduces the API of usbnet_link_change, so that
usbnet can trace the link change, which may help to implement
the later runtime PM triggered by usb ethernet link change.

Signed-off-by: Ming Lei <ming.lei-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
---
 drivers/net/usb/usbnet.c   |   11 +++++++++++
 include/linux/usb/usbnet.h |    2 +-
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index e944109..95a96b1 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1591,6 +1591,17 @@ int usbnet_resume (struct usb_interface *intf)
 }
 EXPORT_SYMBOL_GPL(usbnet_resume);
 
+void usbnet_link_change(struct usbnet *dev, int link, int need_reset)
+{
+	if (link)
+		netif_carrier_on(dev->net);
+	else
+		netif_carrier_off(dev->net);
+
+	if (need_reset && link)
+		usbnet_defer_kevent(dev, EVENT_LINK_RESET);
+}
+EXPORT_SYMBOL_GPL(usbnet_link_change);
 
 /*-------------------------------------------------------------------------*/
 
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index f87cf62..1937b74 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -160,7 +160,7 @@ extern int usbnet_probe(struct usb_interface *, const struct usb_device_id *);
 extern int usbnet_suspend(struct usb_interface *, pm_message_t);
 extern int usbnet_resume(struct usb_interface *);
 extern void usbnet_disconnect(struct usb_interface *);

^ permalink raw reply related

* Re: Remarks and comments about ipconfig behavior
From: Erwan Velu @ 2012-09-15 16:18 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20120913.163134.361379133013906511.davem@davemloft.net>

Le 13/09/2012 22:31, David Miller a écrit :
> I've seen PHY/switch/hub combinations that take longer than 30 seconds to fully negotiate the link. There is really no upper limit to the link speed/duplex/etc. negoatiation process. Even if the actual negoatiation protocol had an upper limit on negoatiation time, hardware implementations do things like try sampling the quality of the cable signal and may choose to down-rev the advertised features and restart the negoatiation. 

I do understand that some might need some longer values while some others like me really need a smaller one.

On my case, this 2mn wait breaks an hardware watchdog, so I did a small patch on my local build to get it reduced as I know  the selected value works fine for this hardware setup. And it works now perfectly.

So could it be valuable to export it as a CONFIG_something instead of patching this #define ?

Cheers,

^ permalink raw reply

* Re: [PATCH net-next 1/2] net: provide a default dev->ethtool_ops
From: Ben Hutchings @ 2012-09-15 13:40 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David Miller, netdev, Maciej Żenczykowski
In-Reply-To: <1347607441.8555.265.camel@edumazet-glaptop>

On Fri, 2012-09-14 at 09:24 +0200, Eric Dumazet wrote:
> From: Eric Dumazet <edumazet@google.com>
> 
> Instead of forcing device drivers to provide empty ethtool_ops or tweak
> net/core/ethtool.c again, we could provide a generic ethtool_ops.
> 
> This occurred to me when I wanted to add GSO support to GRE tunnels.
> ethtool -k support should be generic for all drivers.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Cc: Maciej Żenczykowski <maze@google.com>

Yes, I should have done this ages ago.  Just some nit-picking below:

[...]
> diff --git a/net/core/dev.c b/net/core/dev.c
> index b1e6d63..ff8dcfc 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -6045,6 +6045,11 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
>  
>  	strcpy(dev->name, name);
>  	dev->group = INIT_NETDEV_GROUP;
> +	if (!dev->ethtool_ops) {
> +		static const struct ethtool_ops default_ethtool_ops;
> +
> +		dev->ethtool_ops = &default_ethtool_ops;
> +	}

This block has a blank line in it, so I think it needs a blank line
either side to make the visual grouping of code right.  Alternately you
could pull the variable out of the block.

[...] 
> @@ -1410,8 +1409,9 @@ static int ethtool_get_module_eeprom(struct net_device *dev,
>  				      modinfo.eeprom_len);
>  }
>  
> -/* The main entry point in this file.  Called from net/core/dev.c */
> -
> +/* The main entry point in this file.  Called from net/core/dev.c
> + * with RTNL held.
> + */

Good point but an unrelated change.

>  int dev_ethtool(struct net *net, struct ifreq *ifr)
>  {
>  	struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name);
> @@ -1419,25 +1419,15 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
>  	u32 ethcmd;
>  	int rc;
>  	u32 old_features;
> +	const struct ethtool_ops *ops;
>  
>  	if (!dev || !netif_device_present(dev))
>  		return -ENODEV;
>  
> +	ops = dev->ethtool_ops;
[...]

Introducing this local variable is a useful cleanup but again should be
a separate change.

Ben.

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* Re: interrupt coalescing and CSUM offload
From: Joakim Tjernlund @ 2012-09-15 12:09 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev
In-Reply-To: <20120914093252.020992cc@nehalam.linuxnetplumber.net>

Stephen Hemminger <shemminger@vyatta.com> wrote on 2012/09/14 18:32:52:
>
> On Fri, 14 Sep 2012 16:35:13 +0200
> Joakim Tjernlund <joakim.tjernlund@transmode.se> wrote:
>
> >
> > I am adding interrupt coalescing to the ucc_geth driver. Unfortunately
> > there is only support for RX interrupt coalescing.
> > I wonder if there is any way "simulate" TX interrupt coalescing?
> >
> > I am also looking at adding HWCSUM support but this device can only do
> > IP header CSUM offload. This doesn't seem to be an option in Linux?
> > As I understand it, one must do CSUM offload for the whole frame, both
> > IP header and TCP/UDP csums?
> >
> >  Jocke
>
> There are a few drivers that turn off TX interrupt completely.
> They cleanup TX buffers on next send and have a timer to cleanup

Only on send? Currently ucc_geth does TX free in napi(where RX is processed too).
It would be nice if one could indicate to the drivers xmit() if there
are more frames to be sent. Then xmit() could choose not to turn on TX irq for
preceding frames.

> as well. This has performance benefits, but it does cause issues
> with local flow control (the freeing of skb is used to rate
> limit local traffic).

Was my reasoning correct w.r.t CSUM?

^ permalink raw reply

* [PATCH] sched: fix virtual-start-time update in QFQ
From: Paolo Valente @ 2012-09-15 10:41 UTC (permalink / raw)
  To: davem, shemminger, jhs
  Cc: fchecconi, rizzo, netdev, linux-kernel, paolo.valente

If the old timestamps of a class, say cl, are stale when the class
becomes active, then QFQ may assign to cl a much higher start time
than the maximum value allowed. This may happen when QFQ assigns to
the start time of cl the finish time of a group whose classes are
characterized by a higher value of the ratio
max_class_pkt/weight_of_the_class with respect to that of
cl. Inserting a class with a too high start time into the bucket list
corrupts the data structure and may eventually lead to crashes.
This patch limits the maximum start time assigned to a class.

Signed-off-by: Paolo Valente <paolo.valente@unimore.it>
---
 net/sched/sch_qfq.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c
index e4723d3..211a212 100644
--- a/net/sched/sch_qfq.c
+++ b/net/sched/sch_qfq.c
@@ -865,7 +865,10 @@ static void qfq_update_start(struct qfq_sched *q, struct qfq_class *cl)
 		if (mask) {
 			struct qfq_group *next = qfq_ffs(q, mask);
 			if (qfq_gt(roundedF, next->F)) {
-				cl->S = next->F;
+				if (qfq_gt(limit, next->F))
+					cl->S = next->F;
+				else /* preserve timestamp correctness */
+					cl->S = limit;
 				return;
 			}
 		}
-- 
1.7.9.5

^ permalink raw reply related

* Re: inet_gifconf question
From: David Miller @ 2012-09-15  4:01 UTC (permalink / raw)
  To: alan; +Cc: netdev
In-Reply-To: <20120914230935.65a3769b@pyramind.ukuu.org.uk>

From: Alan Cox <alan@lxorguk.ukuu.org.uk>
Date: Fri, 14 Sep 2012 23:09:35 +0100

> Can anyone tell me what inet_gifconf is meant to be doing with the test
> of ifa->ifa_label against NULL when ifa->ifa_label is an array ?

It wasn't always an array, and this spot got missed during the
conversion it seems.

^ permalink raw reply

* Re: [PATCH 24/24] net: seeq: use __iomem pointers for MMIO
From: David Miller @ 2012-09-15  4:00 UTC (permalink / raw)
  To: linux; +Cc: arnd, linux-arm-kernel, linux-kernel, will.deacon, nico, netdev
In-Reply-To: <20120914235607.GF12245@n2100.arm.linux.org.uk>

From: Russell King - ARM Linux <linux@arm.linux.org.uk>
Date: Sat, 15 Sep 2012 00:56:07 +0100

> On Fri, Sep 14, 2012 at 11:34:52PM +0200, Arnd Bergmann wrote:
>> ARM is moving to stricter checks on readl/write functions,
>> so we need to use the correct types everywhere.
> 
> Same comment as for eesox.  const void __iomem * is not a problem on
> x86, so it should not be a problem on ARM.

Agreed.

^ permalink raw reply

* Re: [PATCH 24/24] net: seeq: use __iomem pointers for MMIO
From: Russell King - ARM Linux @ 2012-09-14 23:56 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Nicolas Pitre, netdev, Will Deacon, linux-kernel, David S. Miller,
	linux-arm-kernel
In-Reply-To: <1347658492-11608-25-git-send-email-arnd@arndb.de>

On Fri, Sep 14, 2012 at 11:34:52PM +0200, Arnd Bergmann wrote:
> ARM is moving to stricter checks on readl/write functions,
> so we need to use the correct types everywhere.

Same comment as for eesox.  const void __iomem * is not a problem on
x86, so it should not be a problem on ARM.

^ permalink raw reply

* inet_gifconf question
From: Alan Cox @ 2012-09-14 22:09 UTC (permalink / raw)
  To: netdev

Can anyone tell me what inet_gifconf is meant to be doing with the test
of ifa->ifa_label against NULL when ifa->ifa_label is an array ?

Alan

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox