[PATCH 04/25] USB OTG Langwell: Update OTG State machine timers.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Hao Wu <hao.wu@xxxxxxxxx>

This patch enables kernel timers for OTG State machine.
Hardware timer will not work once the PHY enters in Low
power mode (clock gated).

Main changes:
- Enable kernel timers instead of hardware timer in PHY low power mode.
- Add timer for SRP failure case.
- Correct the timeout value.

Signed-off-by: Hao Wu <hao.wu@xxxxxxxxx>
Signed-off-by: Alan Cox <alan@xxxxxxxxxxxxxxx>
---

 drivers/usb/otg/langwell_otg.c   |  181 +++++++++++++++++++++++++++-----------
 include/linux/usb/langwell_otg.h |   20 ++++
 2 files changed, 147 insertions(+), 54 deletions(-)


diff --git a/drivers/usb/otg/langwell_otg.c b/drivers/usb/otg/langwell_otg.c
index 2cbfec5..1b6124e 100644
--- a/drivers/usb/otg/langwell_otg.c
+++ b/drivers/usb/otg/langwell_otg.c
@@ -128,9 +128,8 @@ static inline struct langwell_otg_timer *otg_timer_initializer
 	return timer;
 }
 
-static struct langwell_otg_timer *a_wait_vrise_tmr, *a_wait_bcon_tmr,
-	*a_aidl_bdis_tmr, *b_ase0_brst_tmr, *b_se0_srp_tmr, *b_srp_res_tmr,
-	*b_bus_suspend_tmr;
+static struct langwell_otg_timer *a_wait_vrise_tmr, *a_aidl_bdis_tmr,
+	*b_se0_srp_tmr, *b_srp_init_tmr;
 
 static struct list_head active_timers;
 
@@ -500,30 +499,90 @@ static void langwell_otg_init_timers(struct otg_hsm *hsm)
 	/* HSM used timers */
 	a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE,
 				(unsigned long)&hsm->a_wait_vrise_tmout);
-	a_wait_bcon_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_BCON,
-				(unsigned long)&hsm->a_wait_bcon_tmout);
 	a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, TA_AIDL_BDIS,
 				(unsigned long)&hsm->a_aidl_bdis_tmout);
-	b_ase0_brst_tmr = otg_timer_initializer(&set_tmout, TB_ASE0_BRST,
-				(unsigned long)&hsm->b_ase0_brst_tmout);
 	b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP,
 				(unsigned long)&hsm->b_se0_srp);
-	b_srp_res_tmr = otg_timer_initializer(&set_tmout, TB_SRP_RES,
-				(unsigned long)&hsm->b_srp_res_tmout);
-	b_bus_suspend_tmr = otg_timer_initializer(&set_tmout, TB_BUS_SUSPEND,
-				(unsigned long)&hsm->b_bus_suspend_tmout);
+	b_srp_init_tmr = otg_timer_initializer(&set_tmout, TB_SRP_INIT,
+				(unsigned long)&hsm->b_srp_init_tmout);
 }
 
 /* Free timers */
 static void langwell_otg_free_timers(void)
 {
 	kfree(a_wait_vrise_tmr);
-	kfree(a_wait_bcon_tmr);
 	kfree(a_aidl_bdis_tmr);
-	kfree(b_ase0_brst_tmr);
 	kfree(b_se0_srp_tmr);
-	kfree(b_srp_res_tmr);
-	kfree(b_bus_suspend_tmr);
+	kfree(b_srp_init_tmr);
+}
+
+/* The timeout callback function to set time out bit */
+static void langwell_otg_timer_fn(unsigned long indicator)
+{
+	struct langwell_otg *lnw = the_transceiver;
+
+	*(int *)indicator = 1;
+
+	dev_dbg(&lnw->pdev->dev, "kernel timer - timeout\n");
+
+	langwell_update_transceiver();
+}
+
+/* kernel timer used instead of HW based interrupt */
+static void langwell_otg_add_ktimer(enum langwell_otg_timer_type timers)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	unsigned long		j = jiffies;
+	unsigned long		data, time;
+
+	switch (timers) {
+	case TA_WAIT_VRISE_TMR:
+		lnw->hsm.a_wait_vrise_tmout = 0;
+		data = (unsigned long)&lnw->hsm.a_wait_vrise_tmout;
+		time = TA_WAIT_VRISE;
+		break;
+	case TA_WAIT_BCON_TMR:
+		lnw->hsm.a_wait_bcon_tmout = 0;
+		data = (unsigned long)&lnw->hsm.a_wait_bcon_tmout;
+		time = TA_WAIT_BCON;
+		break;
+	case TA_AIDL_BDIS_TMR:
+		lnw->hsm.a_aidl_bdis_tmout = 0;
+		data = (unsigned long)&lnw->hsm.a_aidl_bdis_tmout;
+		time = TA_AIDL_BDIS;
+		break;
+	case TB_ASE0_BRST_TMR:
+		lnw->hsm.b_ase0_brst_tmout = 0;
+		data = (unsigned long)&lnw->hsm.b_ase0_brst_tmout;
+		time = TB_ASE0_BRST;
+		break;
+	case TB_SRP_INIT_TMR:
+		lnw->hsm.b_srp_init_tmout = 0;
+		data = (unsigned long)&lnw->hsm.b_srp_init_tmout;
+		time = TB_SRP_INIT;
+		break;
+	case TB_SRP_FAIL_TMR:
+		lnw->hsm.b_srp_fail_tmout = 0;
+		data = (unsigned long)&lnw->hsm.b_srp_fail_tmout;
+		time = TB_SRP_FAIL;
+		break;
+	case TB_BUS_SUSPEND_TMR:
+		lnw->hsm.b_bus_suspend_tmout = 0;
+		data = (unsigned long)&lnw->hsm.b_bus_suspend_tmout;
+		time = TB_BUS_SUSPEND;
+		break;
+	default:
+		dev_dbg(&lnw->pdev->dev, "unkown timer, cannot enable it\n");
+		return;
+	}
+
+	lnw->hsm_timer.data = data;
+	lnw->hsm_timer.function = langwell_otg_timer_fn;
+	lnw->hsm_timer.expires = j + time * HZ / 1000; /* milliseconds */
+
+	add_timer(&lnw->hsm_timer);
+
+	dev_dbg(&lnw->pdev->dev, "add timer successfully\n");
 }
 
 /* Add timer to timer list */
@@ -806,7 +865,8 @@ static void langwell_otg_work(struct work_struct *work)
 	case OTG_STATE_UNDEFINED:
 	case OTG_STATE_B_IDLE:
 		if (!lnw->hsm.id) {
-			langwell_otg_del_timer(b_srp_res_tmr);
+			langwell_otg_del_timer(b_srp_init_tmr);
+			del_timer_sync(&lnw->hsm_timer);
 			lnw->otg.default_a = 1;
 			lnw->hsm.a_srp_det = 0;
 			langwell_otg_chrg_vbus(0);
@@ -815,12 +875,16 @@ static void langwell_otg_work(struct work_struct *work)
 			langwell_otg_phy_low_power(1);
 			lnw->otg.state = OTG_STATE_A_IDLE;
 			queue_work(lnw->qwork, &lnw->work);
-		} else if (lnw->hsm.b_srp_res_tmout) {
-			lnw->hsm.b_srp_res_tmout = 0;
+		} else if (lnw->hsm.b_srp_init_tmout) {
+			lnw->hsm.b_srp_init_tmout = 0;
+			dev_warn(&lnw->pdev->dev, "SRP init timeout\n");
+		} else if (lnw->hsm.b_srp_fail_tmout) {
+			lnw->hsm.b_srp_fail_tmout = 0;
 			lnw->hsm.b_bus_req = 0;
 			langwell_otg_nsf_msg(6);
 		} else if (lnw->hsm.b_sess_vld) {
-			langwell_otg_del_timer(b_srp_res_tmr);
+			langwell_otg_del_timer(b_srp_init_tmr);
+			del_timer_sync(&lnw->hsm_timer);
 			lnw->hsm.b_sess_end = 0;
 			lnw->hsm.a_bus_suspend = 0;
 			langwell_otg_chrg_vbus(0);
@@ -833,6 +897,7 @@ static void langwell_otg_work(struct work_struct *work)
 
 		} else if (lnw->hsm.b_bus_req &&
 				(lnw->hsm.b_sess_end)) {
+			del_timer_sync(&lnw->hsm_timer);
 			/* workaround for b_se0_srp detection */
 			retval = langwell_otg_check_se0_srp(0);
 			if (retval) {
@@ -844,9 +909,10 @@ static void langwell_otg_work(struct work_struct *work)
 				langwell_otg_phy_low_power(0);
 
 				/* Start SRP */
-				langwell_otg_add_timer(b_srp_res_tmr);
+				langwell_otg_add_timer(b_srp_init_tmr);
 				langwell_otg_start_srp(&lnw->otg);
-				langwell_otg_del_timer(b_srp_res_tmr);
+				langwell_otg_del_timer(b_srp_init_tmr);
+				langwell_otg_add_ktimer(TB_SRP_FAIL_TMR);
 
 				/* reset PHY low power mode here */
 				langwell_otg_phy_low_power_wait(1);
@@ -925,14 +991,14 @@ static void langwell_otg_work(struct work_struct *work)
 					"host driver not loaded.\n");
 
 			lnw->hsm.a_bus_resume = 0;
-			lnw->hsm.b_ase0_brst_tmout = 0;
-			langwell_otg_add_timer(b_ase0_brst_tmr);
+			langwell_otg_add_ktimer(TB_ASE0_BRST_TMR);
 		}
 		break;
 
 	case OTG_STATE_B_WAIT_ACON:
 		if (!lnw->hsm.id) {
-			langwell_otg_del_timer(b_ase0_brst_tmr);
+			/* delete hsm timer for b_ase0_brst_tmr */
+			del_timer_sync(&lnw->hsm_timer);
 			lnw->otg.default_a = 1;
 			lnw->hsm.a_srp_det = 0;
 
@@ -950,7 +1016,8 @@ static void langwell_otg_work(struct work_struct *work)
 			lnw->otg.state = OTG_STATE_A_IDLE;
 			queue_work(lnw->qwork, &lnw->work);
 		} else if (!lnw->hsm.b_sess_vld) {
-			langwell_otg_del_timer(b_ase0_brst_tmr);
+			/* delete hsm timer for b_ase0_brst_tmr */
+			del_timer_sync(&lnw->hsm_timer);
 			lnw->hsm.b_hnp_enable = 0;
 			lnw->hsm.b_bus_req = 0;
 			langwell_otg_chrg_vbus(0);
@@ -966,13 +1033,15 @@ static void langwell_otg_work(struct work_struct *work)
 			langwell_otg_phy_low_power(1);
 			lnw->otg.state = OTG_STATE_B_IDLE;
 		} else if (lnw->hsm.a_conn) {
-			langwell_otg_del_timer(b_ase0_brst_tmr);
+			/* delete hsm timer for b_ase0_brst_tmr */
+			del_timer_sync(&lnw->hsm_timer);
 			langwell_otg_HAAR(0);
 			lnw->otg.state = OTG_STATE_B_HOST;
 			queue_work(lnw->qwork, &lnw->work);
 		} else if (lnw->hsm.a_bus_resume ||
 				lnw->hsm.b_ase0_brst_tmout) {
-			langwell_otg_del_timer(b_ase0_brst_tmr);
+			/* delete hsm timer for b_ase0_brst_tmr */
+			del_timer_sync(&lnw->hsm_timer);
 			langwell_otg_HAAR(0);
 			langwell_otg_nsf_msg(7);
 
@@ -1105,8 +1174,7 @@ static void langwell_otg_work(struct work_struct *work)
 				break;
 			}
 			lnw->hsm.b_conn = 0;
-			lnw->hsm.a_wait_bcon_tmout = 0;
-			langwell_otg_add_timer(a_wait_bcon_tmr);
+			langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
 			lnw->otg.state = OTG_STATE_A_WAIT_BCON;
 		} else if (lnw->hsm.a_wait_vrise_tmout) {
 			if (lnw->hsm.a_vbus_vld) {
@@ -1120,8 +1188,7 @@ static void langwell_otg_work(struct work_struct *work)
 					break;
 				}
 				lnw->hsm.b_conn = 0;
-				lnw->hsm.a_wait_bcon_tmout = 0;
-				langwell_otg_add_timer(a_wait_bcon_tmr);
+				langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
 				lnw->otg.state = OTG_STATE_A_WAIT_BCON;
 			} else {
 				langwell_otg_drv_vbus(0);
@@ -1132,7 +1199,8 @@ static void langwell_otg_work(struct work_struct *work)
 		break;
 	case OTG_STATE_A_WAIT_BCON:
 		if (lnw->hsm.id) {
-			langwell_otg_del_timer(a_wait_bcon_tmr);
+			/* delete hsm timer for a_wait_bcon_tmr */
+			del_timer_sync(&lnw->hsm_timer);
 
 			lnw->otg.default_a = 0;
 			lnw->hsm.b_bus_req = 0;
@@ -1147,7 +1215,8 @@ static void langwell_otg_work(struct work_struct *work)
 			lnw->otg.state = OTG_STATE_B_IDLE;
 			queue_work(lnw->qwork, &lnw->work);
 		} else if (!lnw->hsm.a_vbus_vld) {
-			langwell_otg_del_timer(a_wait_bcon_tmr);
+			/* delete hsm timer for a_wait_bcon_tmr */
+			del_timer_sync(&lnw->hsm_timer);
 
 			if (lnw->host_ops)
 				lnw->host_ops->remove(lnw->pdev);
@@ -1160,7 +1229,8 @@ static void langwell_otg_work(struct work_struct *work)
 		} else if (lnw->hsm.a_bus_drop ||
 				(lnw->hsm.a_wait_bcon_tmout &&
 				!lnw->hsm.a_bus_req)) {
-			langwell_otg_del_timer(a_wait_bcon_tmr);
+			/* delete hsm timer for a_wait_bcon_tmr */
+			del_timer_sync(&lnw->hsm_timer);
 
 			if (lnw->host_ops)
 				lnw->host_ops->remove(lnw->pdev);
@@ -1170,7 +1240,8 @@ static void langwell_otg_work(struct work_struct *work)
 			langwell_otg_drv_vbus(0);
 			lnw->otg.state = OTG_STATE_A_WAIT_VFALL;
 		} else if (lnw->hsm.b_conn) {
-			langwell_otg_del_timer(a_wait_bcon_tmr);
+			/* delete hsm timer for a_wait_bcon_tmr */
+			del_timer_sync(&lnw->hsm_timer);
 
 			lnw->hsm.a_suspend_req = 0;
 			lnw->otg.state = OTG_STATE_A_HOST;
@@ -1199,9 +1270,11 @@ static void langwell_otg_work(struct work_struct *work)
 				langwell_otg_HABA(1);
 				lnw->hsm.b_bus_resume = 0;
 				lnw->hsm.a_aidl_bdis_tmout = 0;
-				langwell_otg_add_timer(a_aidl_bdis_tmr);
 
 				langwell_otg_loc_sof(0);
+				/* clear PHCD to enable HW timer */
+				langwell_otg_phy_low_power(0);
+				langwell_otg_add_timer(a_aidl_bdis_tmr);
 				lnw->otg.state = OTG_STATE_A_SUSPEND;
 			} else if (!lnw->hsm.a_bus_req &&
 				!lnw->otg.host->b_hnp_enable) {
@@ -1268,12 +1341,13 @@ static void langwell_otg_work(struct work_struct *work)
 			langwell_otg_HABA(1);
 			lnw->hsm.b_bus_resume = 0;
 			lnw->hsm.a_aidl_bdis_tmout = 0;
-			langwell_otg_add_timer(a_aidl_bdis_tmr);
 			langwell_otg_loc_sof(0);
+			/* clear PHCD to enable HW timer */
+			langwell_otg_phy_low_power(0);
+			langwell_otg_add_timer(a_aidl_bdis_tmr);
 			lnw->otg.state = OTG_STATE_A_SUSPEND;
 		} else if (!lnw->hsm.b_conn || !lnw->hsm.a_bus_req) {
-			lnw->hsm.a_wait_bcon_tmout = 0;
-			langwell_otg_add_timer(a_wait_bcon_tmr);
+			langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
 			lnw->otg.state = OTG_STATE_A_WAIT_BCON;
 		}
 		break;
@@ -1337,7 +1411,7 @@ static void langwell_otg_work(struct work_struct *work)
 				dev_dbg(&lnw->pdev->dev,
 					"client driver not loaded.\n");
 
-			langwell_otg_add_timer(b_bus_suspend_tmr);
+			langwell_otg_add_ktimer(TB_BUS_SUSPEND_TMR);
 			lnw->otg.state = OTG_STATE_A_PERIPHERAL;
 			break;
 		} else if (!lnw->hsm.a_vbus_vld) {
@@ -1356,7 +1430,8 @@ static void langwell_otg_work(struct work_struct *work)
 		break;
 	case OTG_STATE_A_PERIPHERAL:
 		if (lnw->hsm.id) {
-			langwell_otg_del_timer(b_bus_suspend_tmr);
+			/* delete hsm timer for b_bus_suspend_tmr */
+			del_timer_sync(&lnw->hsm_timer);
 			lnw->otg.default_a = 0;
 			lnw->hsm.b_bus_req = 0;
 			if (lnw->client_ops)
@@ -1371,7 +1446,8 @@ static void langwell_otg_work(struct work_struct *work)
 			lnw->otg.state = OTG_STATE_B_IDLE;
 			queue_work(lnw->qwork, &lnw->work);
 		} else if (!lnw->hsm.a_vbus_vld) {
-			langwell_otg_del_timer(b_bus_suspend_tmr);
+			/* delete hsm timer for b_bus_suspend_tmr */
+			del_timer_sync(&lnw->hsm_timer);
 			if (lnw->client_ops)
 				lnw->client_ops->suspend(lnw->pdev,
 					PMSG_FREEZE);
@@ -1382,7 +1458,9 @@ static void langwell_otg_work(struct work_struct *work)
 			langwell_otg_phy_low_power_wait(1);
 			lnw->otg.state = OTG_STATE_A_VBUS_ERR;
 		} else if (lnw->hsm.a_bus_drop) {
-			langwell_otg_del_timer(b_bus_suspend_tmr);
+			/* delete hsm timer for b_bus_suspend_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+
 			if (lnw->client_ops)
 				lnw->client_ops->suspend(lnw->pdev,
 					PMSG_FREEZE);
@@ -1392,7 +1470,8 @@ static void langwell_otg_work(struct work_struct *work)
 			langwell_otg_drv_vbus(0);
 			lnw->otg.state = OTG_STATE_A_WAIT_VFALL;
 		} else if (lnw->hsm.b_bus_suspend) {
-			langwell_otg_del_timer(b_bus_suspend_tmr);
+			/* delete hsm timer for b_bus_suspend_tmr */
+			del_timer_sync(&lnw->hsm_timer);
 			if (lnw->client_ops)
 				lnw->client_ops->suspend(lnw->pdev,
 					PMSG_FREEZE);
@@ -1405,8 +1484,7 @@ static void langwell_otg_work(struct work_struct *work)
 			else
 				dev_dbg(&lnw->pdev->dev,
 					"host driver not loaded.\n");
-			lnw->hsm.a_wait_bcon_tmout = 0;
-			langwell_otg_add_timer(a_wait_bcon_tmr);
+			langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
 			lnw->otg.state = OTG_STATE_A_WAIT_BCON;
 		} else if (lnw->hsm.b_bus_suspend_tmout) {
 			u32	val;
@@ -1425,8 +1503,7 @@ static void langwell_otg_work(struct work_struct *work)
 			else
 				dev_dbg(&lnw->pdev->dev,
 					"host driver not loaded.\n");
-			lnw->hsm.a_wait_bcon_tmout = 0;
-			langwell_otg_add_timer(a_wait_bcon_tmr);
+			langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
 			lnw->otg.state = OTG_STATE_A_WAIT_BCON;
 		}
 		break;
@@ -2030,7 +2107,7 @@ static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message)
 		transceiver_suspend(pdev);
 		break;
 	case OTG_STATE_A_WAIT_BCON:
-		langwell_otg_del_timer(a_wait_bcon_tmr);
+		del_timer_sync(&langwell->hsm_timer);
 		if (langwell->host_ops)
 			ret = langwell->host_ops->suspend(pdev, message);
 		else
@@ -2057,6 +2134,7 @@ static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message)
 		langwell->otg.state = OTG_STATE_A_WAIT_VFALL;
 		break;
 	case OTG_STATE_A_PERIPHERAL:
+		del_timer_sync(&langwell->hsm_timer);
 		if (langwell->client_ops)
 			ret = langwell->client_ops->suspend(pdev, message);
 		else
@@ -2083,7 +2161,8 @@ static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message)
 				"client driver has been removed.\n");
 		break;
 	case OTG_STATE_B_WAIT_ACON:
-		langwell_otg_del_timer(b_ase0_brst_tmr);
+		/* delete hsm timer for b_ase0_brst_tmr */
+		del_timer_sync(&langwell->hsm_timer);
 		langwell_otg_HAAR(0);
 		if (langwell->host_ops)
 			langwell->host_ops->remove(pdev);
@@ -2124,7 +2203,7 @@ static int langwell_otg_resume(struct pci_dev *pdev)
 		transceiver_resume(pdev);
 		break;
 	case OTG_STATE_A_WAIT_BCON:
-		langwell_otg_add_timer(a_wait_bcon_tmr);
+		langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
 		langwell_otg_drv_vbus(1);
 		if (langwell->host_ops)
 			ret = langwell->host_ops->resume(pdev);
diff --git a/include/linux/usb/langwell_otg.h b/include/linux/usb/langwell_otg.h
index 64ff588..69977c2 100644
--- a/include/linux/usb/langwell_otg.h
+++ b/include/linux/usb/langwell_otg.h
@@ -120,7 +120,8 @@ struct otg_hsm {
 	int a_aidl_bdis_tmout;
 	int b_ase0_brst_tmout;
 	int b_bus_suspend_tmout;
-	int b_srp_res_tmout;
+	int b_srp_init_tmout;
+	int b_srp_fail_tmout;
 
 	/* Informative variables */
 	int a_bus_drop;
@@ -139,12 +140,24 @@ struct otg_hsm {
 	int vbus_srp_up;
 };
 
-#define TA_WAIT_VRISE	200
+enum langwell_otg_timer_type {
+	TA_WAIT_VRISE_TMR,
+	TA_WAIT_BCON_TMR,
+	TA_AIDL_BDIS_TMR,
+	TB_ASE0_BRST_TMR,
+	TB_SE0_SRP_TMR,
+	TB_SRP_INIT_TMR,
+	TB_SRP_FAIL_TMR,
+	TB_BUS_SUSPEND_TMR
+};
+
+#define TA_WAIT_VRISE	100
 #define TA_WAIT_BCON	30000
 #define TA_AIDL_BDIS	15000
 #define TB_ASE0_BRST	5000
 #define TB_SE0_SRP	2
-#define TB_SRP_RES	100
+#define TB_SRP_INIT	100
+#define TB_SRP_FAIL	5500
 #define TB_BUS_SUSPEND	500
 
 struct langwell_otg_timer {
@@ -167,6 +180,7 @@ struct langwell_otg {
 	struct pci_dev		*pdev;
 	struct work_struct	work;
 	struct workqueue_struct	*qwork;
+	struct timer_list	hsm_timer;
 	spinlock_t		lock;
 	spinlock_t		wq_lock;
 };

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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux