diff --git a/dde_linux/files.list b/dde_linux/files.list
index a600543a6..4c1ab1f6b 100644
--- a/dde_linux/files.list
+++ b/dde_linux/files.list
@@ -123,6 +123,7 @@ linux-3.9/drivers/usb/host/xhci-ext-caps.h
linux-3.9/drivers/usb/host/xhci.h
linux-3.9/drivers/usb/host/xhci-hub.c
linux-3.9/drivers/usb/host/xhci-mem.c
+linux-3.9/drivers/usb/host/xhci-pci.c
linux-3.9/drivers/usb/host/xhci-plat.c
linux-3.9/drivers/usb/host/xhci-ring.c
linux-3.9/drivers/usb/storage/alauda.c
diff --git a/dde_linux/lib/mk/platform_arndale/usb.mk b/dde_linux/lib/mk/platform_arndale/usb.mk
index 7694265d0..97e56e1ef 100644
--- a/dde_linux/lib/mk/platform_arndale/usb.mk
+++ b/dde_linux/lib/mk/platform_arndale/usb.mk
@@ -1,5 +1,6 @@
SRC_C += usbnet.c asix_devices.c asix_common.c ax88172a.c ax88179_178a.c
+include $(REP_DIR)/lib/mk/xhci.inc
include $(REP_DIR)/lib/mk/usb.inc
include $(REP_DIR)/lib/mk/arm/usb.inc
@@ -12,7 +13,7 @@ SRC_CC += platform.cc
SRC_C += dwc3-exynos.c host.c core.c
#XHCI
-SRC_C += xhci-dbg.c xhci-hub.c xhci-mem.c xhci-plat.c xhci-ring.c xhci.c
+SRC_C += xhci-plat.c
vpath platform.cc $(LIB_DIR)/arm/platform_arndale
vpath %.c $(CONTRIB_DIR)/drivers/usb/dwc3
diff --git a/dde_linux/lib/mk/usb_x86.inc b/dde_linux/lib/mk/usb_x86.inc
new file mode 100644
index 000000000..522f0ae3b
--- /dev/null
+++ b/dde_linux/lib/mk/usb_x86.inc
@@ -0,0 +1,21 @@
+SRC_C += $(addprefix usb/host/,pci-quirks.c uhci-hcd.c ehci-pci.c)
+
+#
+# USB netwpork support
+#
+SRC_C += usbnet.c ax88179_178a.c
+
+#XHCI
+SRC_C += xhci-pci.c
+
+SRC_CC += pci_driver.cc platform.cc
+
+include $(REP_DIR)/lib/mk/xhci.inc
+include $(REP_DIR)/lib/mk/usb.inc
+
+CC_OPT += -DCONFIG_PCI -DCONFIG_USB_EHCI_PCI=1 -DCONFIG_USB_XHCI_HCD=1
+
+vpath platform.cc $(LIB_DIR)/x86
+vpath %.c $(CONTRIB_DIR)/drivers/net/usb
+
+# vi:set ft=make :
diff --git a/dde_linux/lib/mk/x86_32/usb.mk b/dde_linux/lib/mk/x86_32/usb.mk
index b87eaca3d..8f7568c5e 100644
--- a/dde_linux/lib/mk/x86_32/usb.mk
+++ b/dde_linux/lib/mk/x86_32/usb.mk
@@ -1,9 +1,4 @@
-SRC_C += $(addprefix usb/host/,pci-quirks.c uhci-hcd.c ehci-pci.c)
-
-include $(REP_DIR)/lib/mk/usb.inc
-
-CC_OPT += -DCONFIG_PCI -DCONFIG_USB_EHCI_PCI=1 -DCONFIG_USB_XHCI_HCD=0
INC_DIR += $(LIB_INC_DIR)/x86_32 $(LIB_INC_DIR)/x86
-SRC_CC += pci_driver.cc platform.cc
-vpath platform.cc $(LIB_DIR)/x86
+include $(REP_DIR)/lib/mk/usb_x86.inc
+
diff --git a/dde_linux/lib/mk/x86_64/usb.mk b/dde_linux/lib/mk/x86_64/usb.mk
index 25cb21fc2..c49ca7eeb 100644
--- a/dde_linux/lib/mk/x86_64/usb.mk
+++ b/dde_linux/lib/mk/x86_64/usb.mk
@@ -1,9 +1,3 @@
-SRC_C += $(addprefix usb/host/,pci-quirks.c uhci-hcd.c ehci-pci.c)
-
-include $(REP_DIR)/lib/mk/usb.inc
-
-CC_OPT += -DCONFIG_PCI -DCONFIG_USB_EHCI_PCI=1 -DCONFIG_USB_XHCI_HCD=0
INC_DIR += $(LIB_INC_DIR)/x86_64 $(LIB_INC_DIR)/x86
-SRC_CC += pci_driver.cc platform.cc
-vpath platform.cc $(LIB_DIR)/x86
+include $(REP_DIR)/lib/mk/usb_x86.inc
diff --git a/dde_linux/lib/mk/xhci.inc b/dde_linux/lib/mk/xhci.inc
new file mode 100644
index 000000000..8a2a95ac2
--- /dev/null
+++ b/dde_linux/lib/mk/xhci.inc
@@ -0,0 +1,6 @@
+#
+# Generic XHCI files
+#
+SRC_C += xhci-dbg.c xhci-hub.c xhci-mem.c xhci-ring.c xhci.c
+
+# vi:set ft=make :
diff --git a/dde_linux/patches/dw3_quirk.patch b/dde_linux/patches/dw3_quirk.patch
deleted file mode 100644
index d08aa5d28..000000000
--- a/dde_linux/patches/dw3_quirk.patch
+++ /dev/null
@@ -1,20 +0,0 @@
-diff -r 6978f825431c drivers/usb/host/xhci-plat.c
---- a/drivers/usb/host/xhci-plat.c Thu May 16 15:54:34 2013 +0200
-+++ b/drivers/usb/host/xhci-plat.c Thu May 16 16:41:46 2013 +0200
-@@ -25,6 +25,16 @@
- * dev struct in order to setup MSI
- */
- xhci->quirks |= XHCI_BROKEN_MSI;
-+
-+#ifdef DWC3_QUIRK
-+ /*
-+ * DWC3 controller
-+ * One will see 'dev_error: ERROR Transfer event TRB DMA ptr not part of
-+ * current TD' and last message was short (ep_ring->last_td_was_short, in
-+ * xhci-ring.c
-+ */
-+ xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
-+#endif
- }
-
- /* called during probe() after chip reset completes */
diff --git a/dde_linux/patches/xhci-quirks.patch b/dde_linux/patches/xhci-quirks.patch
new file mode 100644
index 000000000..96f52ea3b
--- /dev/null
+++ b/dde_linux/patches/xhci-quirks.patch
@@ -0,0 +1,43 @@
+diff -r a103aef8f269 drivers/usb/host/.xhci-pci.c.swp
+Binary file drivers/usb/host/.xhci-pci.c.swp has changed
+diff -r a103aef8f269 drivers/usb/host/xhci-pci.c
+--- a/drivers/usb/host/xhci-pci.c Wed Mar 05 13:54:43 2014 +0100
++++ b/drivers/usb/host/xhci-pci.c Wed Mar 05 13:58:50 2014 +0100
+@@ -34,6 +34,8 @@
+ #define PCI_VENDOR_ID_ETRON 0x1b6f
+ #define PCI_DEVICE_ID_ASROCK_P67 0x7023
+
++#define PCI_VENDOR_ID_RENESAS 0x1912
++
+ static const char hcd_name[] = "xhci_hcd";
+
+ /* called after powerup, by probe or system-pm "wakeup" */
+@@ -81,6 +83,10 @@
+ if (pdev->vendor == PCI_VENDOR_ID_NEC)
+ xhci->quirks |= XHCI_NEC_HOST;
+
++ /* Quirk for RENESAS USB 3.0 express cards */
++ if (pdev->vendor == PCI_VENDOR_ID_RENESAS)
++ xhci->quirks |= XHCI_TRUST_TX_LENGTH;
++
+ if (pdev->vendor == PCI_VENDOR_ID_AMD && xhci->hci_version == 0x96)
+ xhci->quirks |= XHCI_AMD_0x96_HOST;
+
+diff -r a103aef8f269 drivers/usb/host/xhci.c
+--- a/drivers/usb/host/xhci.c Wed Mar 05 13:54:43 2014 +0100
++++ b/drivers/usb/host/xhci.c Wed Mar 05 13:58:50 2014 +0100
+@@ -4683,6 +4683,14 @@
+
+ get_quirks(dev, xhci);
+
++
++ /* In xhci controllers which follow xhci 1.0 spec gives a spurious
++ * success event after a short transfer. This quirk will ignore such
++ * spurious event (This is taken from Linux 3.13)
++ */
++ if (xhci->hci_version > 0x96)
++ xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
++
+ /* Make sure the HC is halted. */
+ retval = xhci_halt(xhci);
+ if (retval)
diff --git a/dde_linux/run/usb_hid_panda.run b/dde_linux/run/usb_hid_panda.run
new file mode 100644
index 000000000..85a3310d3
--- /dev/null
+++ b/dde_linux/run/usb_hid_panda.run
@@ -0,0 +1,66 @@
+#
+# Build
+#
+
+set build_components {
+ core init
+ drivers/timer
+ drivers/usb
+ test/input
+}
+
+build $build_components
+
+create_boot_directory
+
+#
+# Generate config
+#
+
+append config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+install_config $config
+
+#
+# Boot modules
+#
+
+# generic modules
+set boot_modules {
+ core init timer usb_drv test-input
+}
+
+build_boot_image $boot_modules
+
diff --git a/dde_linux/run/usb_net.run b/dde_linux/run/usb_net.run
index 2c2a4016a..0b3695089 100644
--- a/dde_linux/run/usb_net.run
+++ b/dde_linux/run/usb_net.run
@@ -11,7 +11,7 @@
# Build
#
-build {
+set build_components {
core init
drivers/pci drivers/timer drivers/usb
test/lwip/http_srv
@@ -22,6 +22,7 @@ lappend_if [have_spec pci] build_components drivers/pci/device_pd
lappend_if [have_spec platform_arndale] build_components drivers/platform
lappend_if [have_spec gpio] build_components drivers/gpio
+build $build_components
create_boot_directory
@@ -56,7 +57,7 @@ set config {
-
+
@@ -66,7 +67,7 @@ set config {
append_if [have_spec acpi] config {
-
+
@@ -122,5 +123,7 @@ lappend_if [have_spec gpio] boot_modules gpio_drv
build_boot_image $boot_modules
+append qemu_args " -m 256 -nographic"
+
run_genode_until forever
# vi: set ft=tcl :
diff --git a/dde_linux/src/lib/usb/dummies.c b/dde_linux/src/lib/usb/dummies.c
index 9ab528092..9ad080020 100644
--- a/dde_linux/src/lib/usb/dummies.c
+++ b/dde_linux/src/lib/usb/dummies.c
@@ -611,6 +611,7 @@ bool in_interrupt(void) { TRACE; return 1; }
/*****************
** linux/pci.h **
*****************/
+
int pci_bus_read_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 *val) { TRACE; return 0; }
int pci_bus_write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 val) { TRACE; return 0; }
@@ -633,6 +634,12 @@ const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
struct pci_dev *dev) { TRACE; return 0; }
void *pci_ioremap_bar(struct pci_dev *pdev, int bar);
+int pci_enable_msi(struct pci_dev *pdev) { TRACE; return -1; }
+void pci_disable_msi(struct pci_dev *pdev) { TRACE; }
+
+int pci_enable_msix(struct pci_dev *pdev, struct msix_entry *entries, int vec) { TRACE; return -1; }
+void pci_disable_msix(struct pci_dev *pdev) { TRACE; }
+
/**
* Omitted PCI functions
*/
diff --git a/dde_linux/src/lib/usb/include/lx_emul.h b/dde_linux/src/lib/usb/include/lx_emul.h
index 2b8cc6bdf..5bc0f53c9 100644
--- a/dde_linux/src/lib/usb/include/lx_emul.h
+++ b/dde_linux/src/lib/usb/include/lx_emul.h
@@ -645,6 +645,13 @@ int scnprintf(char *buf, size_t size, const char *fmt, ...);
struct completion;
void complete_and_exit(struct completion *, long);
+
+/*********************
+ ** linux/cpumask.h **
+ *********************/
+
+static inline unsigned num_online_cpus(void) { return 1U; }
+
/******************
** linux/log2.h **
******************/
@@ -1045,11 +1052,13 @@ typedef void (*work_func_t)(struct work_struct *work);
struct work_struct {
work_func_t func;
struct list_head entry;
+ unsigned pending;
};
struct delayed_work {
struct timer_list timer;
struct work_struct work;
+ unsigned pending;
};
bool cancel_work_sync(struct work_struct *work);
@@ -1062,10 +1071,17 @@ bool flush_work_sync(struct work_struct *work);
#define PREPARE_WORK(_work, _func) \
- do { (_work)->func = (_func); } while (0)
+ do { \
+ (_work)->func = (_func); \
+ (_work)->pending = 0; \
+ } while (0)
#define PREPARE_DELAYED_WORK(_work, _func) \
- PREPARE_WORK(&(_work)->work, (_func))
+ do { \
+ PREPARE_WORK(&(_work)->work, (_func)); \
+ (_work)->pending = 0; \
+ } while (0)
+
#define __INIT_WORK(_work, _func, on_stack) \
do { \
@@ -1080,6 +1096,7 @@ bool flush_work_sync(struct work_struct *work);
do { \
INIT_WORK(&(_work)->work, (_func)); \
init_timer(&(_work)->timer); \
+ (_work)->pending = 0; \
} while (0)
@@ -2201,12 +2218,9 @@ bool in_interrupt(void);
/*
* Definitions normally found in pci_regs.h
*/
-//enum { PCI_BASE_ADDRESS_MEM_MASK = ~0x0fUL };
-//enum { PCI_CAP_ID_AGP = 0x02 };
extern struct bus_type pci_bus_type;
enum { PCI_ANY_ID = ~0U };
enum { DEVICE_COUNT_RESOURCE = 6 };
-//enum { PCIBIOS_MIN_MEM = 0UL };
#define PCI_DEVICE_CLASS(dev_class,dev_class_mask) \
.class = (dev_class), .class_mask = (dev_class_mask), \
@@ -2232,6 +2246,21 @@ typedef enum { PCI_D0 = 0 } pci_power_t;
#define class device_class
#endif /* __cplusplus */
+struct msix_entry
+{
+ u32 vector;
+ u16 entry;
+};
+
+struct pci_dev;
+
+int pci_enable_msi(struct pci_dev *);
+void pci_disable_msi(struct pci_dev *);
+
+int pci_enable_msix(struct pci_dev *, struct msix_entry *, int);
+void pci_disable_msix(struct pci_dev *);
+
+
#include
/*
@@ -2769,6 +2798,8 @@ int scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len,
int desc_type);
int scsi_sense_valid(struct scsi_sense_hdr *);
+int scsi_sense_is_deferred(struct scsi_sense_hdr *);
+
/*********************
** scsi/scsi_tcq.h **
@@ -3429,6 +3460,7 @@ struct tasklet_struct
{
void (*func)(unsigned long);
unsigned long data;
+ unsigned pending;
};
void tasklet_schedule(struct tasklet_struct *t);
diff --git a/dde_linux/src/lib/usb/include/routine.h b/dde_linux/src/lib/usb/include/routine.h
index bd566d67d..ea3558d2f 100644
--- a/dde_linux/src/lib/usb/include/routine.h
+++ b/dde_linux/src/lib/usb/include/routine.h
@@ -34,7 +34,7 @@ class Routine : public Genode::List::Element
{
private:
- enum { STACK_SIZE = 0x2000 };
+ enum { STACK_SIZE = 4 * 1024 * sizeof(long) };
bool _started; /* true if already started */
jmp_buf _env; /* state */
int (*_func)(void *); /* function to call*/
diff --git a/dde_linux/src/lib/usb/lx_emul.cc b/dde_linux/src/lib/usb/lx_emul.cc
index f1f1659da..811bbd503 100644
--- a/dde_linux/src/lib/usb/lx_emul.cc
+++ b/dde_linux/src/lib/usb/lx_emul.cc
@@ -914,7 +914,7 @@ int fls(int x)
for (int i = 31; i >= 0; i--)
if (x & (1 << i))
- return i;
+ return i + 1;
return 0;
}
diff --git a/dde_linux/src/lib/usb/signal/event.cc b/dde_linux/src/lib/usb/signal/event.cc
index fe563e9ba..80a46a4d6 100644
--- a/dde_linux/src/lib/usb/signal/event.cc
+++ b/dde_linux/src/lib/usb/signal/event.cc
@@ -77,6 +77,10 @@ class Work : public Genode::List::Element
template
static void schedule(WORK *work)
{
+ if (work->pending)
+ return;
+
+ work->pending = 1;
_list()->insert(new (Genode::env()->heap()) Work(work));
}
@@ -92,6 +96,7 @@ class Work : public Genode::List::Element
{
work_struct *work = static_cast(w->_work);
work->func(work);
+ work->pending = 0;
}
break;
@@ -99,6 +104,7 @@ class Work : public Genode::List::Element
{
delayed_work *work = static_cast(w->_work);
work->work.func(&(work)->work);
+ work->pending = 0;
}
break;
@@ -106,6 +112,7 @@ class Work : public Genode::List::Element
{
tasklet_struct *tasklet = static_cast(w->_work);
tasklet->func(tasklet->data);
+ tasklet->pending = 0;
}
break;
}
@@ -269,8 +276,9 @@ bool queue_delayed_work(struct workqueue_struct *wq,
void tasklet_init(struct tasklet_struct *t, void (*f)(unsigned long), unsigned long d)
{
- t->func = f;
- t->data = d;
+ t->func = f;
+ t->data = d;
+ t->pending = 0;
}
diff --git a/dde_linux/src/lib/usb/signal/irq.cc b/dde_linux/src/lib/usb/signal/irq.cc
index de4c9243a..02e8fbc5a 100644
--- a/dde_linux/src/lib/usb/signal/irq.cc
+++ b/dde_linux/src/lib/usb/signal/irq.cc
@@ -120,13 +120,11 @@ class Irq_context : public Genode::List::Element
bool handled = false;
/* report IRQ to all clients */
- for (Irq_handler *h = _handler_list.first(); h; h = h->next()) {
-
- if ((handled = _handle_one(h)))
+ for (Irq_handler *h = _handler_list.first(); h; h = h->next())
+ if ((handled = _handle_one(h))) {
+ dde_kit_log(DEBUG_IRQ, "IRQ: %u ret: %u h: %p dev: %p", _irq, handled, h->handler, h->dev);
break;
-
- dde_kit_log(DEBUG_IRQ, "IRQ: %u ret: %u h: %p dev: %p", _irq, handled, h->handler, h->dev);
- }
+ }
/* interrupt should be acked at device now */
_irq_sync.unlock();
diff --git a/dde_linux/src/lib/usb/x86/platform.cc b/dde_linux/src/lib/usb/x86/platform.cc
index 3e28b11d7..c2cce95f3 100644
--- a/dde_linux/src/lib/usb/x86/platform.cc
+++ b/dde_linux/src/lib/usb/x86/platform.cc
@@ -15,12 +15,23 @@
#include
+extern "C" void module_ax88179_178a_driver_init();
+extern "C" void module_usbnet_init();
extern "C" void module_ehci_hcd_init();
extern "C" void module_ehci_pci_init();
extern "C" void module_uhci_hcd_init();
+extern "C" void module_xhci_hcd_init();
void platform_hcd_init(Services *s)
{
+ if (s->nic) {
+ module_usbnet_init();
+ module_ax88179_178a_driver_init();
+ }
+
+ if (s->xhci)
+ module_xhci_hcd_init();
+
/* ehci_hcd should always be loaded before uhci_hcd and ohci_hcd, not after */
if (s->ehci) {
module_ehci_hcd_init();