dde_linux: update usb to 4.4.3

Issue #1974.
This commit is contained in:
Sebastian Sumpf 2016-05-18 18:51:11 +02:00 committed by Christian Helmuth
parent bcefc874d6
commit 369ff2a001
60 changed files with 1689 additions and 4573 deletions

View File

@ -16,6 +16,20 @@ Configuration snippet to enable UHCI and EHCI
! <config uhci="yes" ehci="yes">
BIOS Handoff
~~~~~~~~~~~~
Per default the USB driver performs a hand off of the USB controller from the
BIOS, since it still may access the controller when booting, for example, from
a USB device. The BIOS hand off induces the execution of BIOS/SMM USB driver
code and potentially DMA operations. Unfortunately, some ACPI tables report
wrong RMRR information, which implicates IOMMU faults on illegal DMA
operations and consequently the hand off may fail after noticeably long
timeouts. Therefore, the hand off can be disabled in the USB driver
configuration like follows.
! <config bios_handoff="no"/>
HID
~~~

View File

@ -0,0 +1,36 @@
USB_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/lib/usb
LIB_DIR := $(REP_DIR)/src/lib/usb
LIB_INC_DIR := $(LIB_DIR)/include
# architecture-dependent includes
ifeq ($(filter-out $(SPECS),x86),)
ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/x86
ifeq ($(filter-out $(SPECS),32bit),)
ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/x86_32
endif # 32bit
ifeq ($(filter-out $(SPECS),64bit),)
ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/x86_64
endif # 64bit
endif # x86
ifeq ($(filter-out $(SPECS),arm),)
ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm
ifeq ($(filter-out $(SPECS),arm_v6),)
ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm_v6
endif # arm_v6
ifeq ($(filter-out $(SPECS),arm_v7),)
ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm_v7
endif # arm_v7
endif # arm
#
# The order of include-search directories is important, we need to look into
# 'contrib' before falling back to our custom 'lx_emul.h' header.
#
INC_DIR += $(LIB_INC_DIR)
INC_DIR += $(ARCH_SRC_INC_DIR)
INC_DIR += $(USB_CONTRIB_DIR)/include
INC_DIR += $(USB_CONTRIB_DIR)/drivers/usb/core
INC_DIR += $(LIB_CACHE_DIR)/usb_include/include/include/include

View File

@ -1,6 +1,11 @@
include $(REP_DIR)/lib/mk/usb.inc
SRC_CC += platform_device.c
INC_DIR += $(LIB_INC_DIR)/spec/arm
SRC_CC += platform_device.cc platform_generic.cc
vpath platform_device.cc $(LIB_DIR)/spec/arm
INC_DIR += $(LIB_INC_DIR)/spec/arm
INC_DIR += $(REP_DIR)/src/include/spec/arm
vpath platform_device.cc $(LIB_DIR)/spec/arm
vpath platform_generic.cc $(LIB_DIR)/spec/arm
# vi:set ft=make :

View File

@ -11,7 +11,7 @@ INC_DIR += $(LX_CONTRIB_DIR)/arch/arm/plat-samsung/include
SRC_CC += platform.cc
#DWC3
SRC_C += $(addprefix usb/dwc3/, host.c core.c)
SRC_C += $(addprefix usb/dwc3/, dwc3-exynos.c host.c core.c)
#XHCI
SRC_C += usb/host/xhci-plat.c

View File

@ -1,20 +1,27 @@
SRC_C += $(addprefix usb/host/,pci-quirks.c uhci-hcd.c ehci-pci.c)
SRC_C += usb/core/hcd-pci.c
#
# USB netwpork support
#
SRC_C += $(addprefix net/usb/, usbnet.c ax88179_178a.c)
#XHCI
# XHCI
SRC_C += usb/host/xhci-pci.c
# PCI
SRC_CC += pci_driver.cc platform.cc
# lx_kit
SRC_CC += pci.cc mapped_io_mem_range.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)/spec/x86
vpath platform.cc $(LIB_DIR)/spec/x86
vpath pci_driver.cc $(LIB_DIR)/spec/x86
# vi:set ft=make :

View File

@ -1,4 +1,5 @@
INC_DIR += $(LIB_INC_DIR)/spec/x86_32 $(LIB_INC_DIR)/spec/x86
INC_DIR += $(REP_DIR)/src/include/spec/x86_32
include $(REP_DIR)/lib/mk/spec/x86/usb.inc

View File

@ -1,3 +1,4 @@
INC_DIR += $(LIB_INC_DIR)/spec/x86_64 $(LIB_INC_DIR)/spec/x86
INC_DIR += $(REP_DIR)/src/include/spec/x86_64
include $(REP_DIR)/lib/mk/spec/x86/usb.inc

View File

@ -1,8 +1,8 @@
LIB_DIR = $(REP_DIR)/src/lib/usb
LIB_INC_DIR = $(LIB_DIR)/include
LIBS += libc-setjmp config
SRC_CC += main.cc lx_emul.cc irq.cc timer.cc event.cc storage.cc \
LIBS += usb_include libc-setjmp config
SRC_CC += main.cc lx_emul.cc storage.cc \
input_component.cc nic.cc raw.cc
SRC_C += dummies.c scsi.c evdev.c raw_driver.c
@ -16,11 +16,13 @@ CC_OLEVEL = -O2
# The order of include-search directories is important, we need to look into
# 'contrib' before falling back to our custom 'lx_emul.h' header.
#
INC_DIR += $(LIB_INC_DIR)
INC_DIR += $(LIB_INC_DIR) $(REP_DIR)/src/include
INC_DIR += $(LX_CONTRIB_DIR)/include $(LX_CONTRIB_DIR)/include/uapi $(LX_CONTRIB_DIR)
CC_OPT += -U__linux__ -D__KERNEL__
CC_OPT += -DCONFIG_USB_DEVICEFS -DCONFIG_HOTPLUG -DDEBUG -DCONFIG_USB_PHY=1
CC_OPT += -DCONFIG_USB_DEVICEFS -DCONFIG_HOTPLUG -DDEBUG -DCONFIG_USB_PHY=1 \
-DCONFIG_GENERIC_PHY=0 -DCONFIG_USB_OTG_WHITELIST=0 \
-DCONFIG_USB_OTG=0
CC_WARN = -Wall -Wno-unused-variable -Wno-uninitialized \
-Wno-unused-function -Wno-overflow
@ -35,22 +37,29 @@ CC_CXX_OPT = -fpermissive
MOD_SUFFIX =
CC_OPT += -DMOD_SUFFIX=$(MOD_SUFFIX)
# lx_kit
SRC_CC += printf.cc work.cc timer.cc scheduler.cc irq.cc malloc.cc
# common lib
SRC_C += lib/int_sqrt.c
# USB core
SRC_C += $(addprefix usb/core/,$(notdir $(wildcard $(USB_DIR)/core/*.c)))
SRC_C += usb/usb-common.c
SRC_C += $(addprefix usb/core/, buffer.c config.c devices.c driver.c endpoint.c file.c \
generic.c hcd.c hub.c message.c notify.c port.c quirks.c\
urb.c usb.c)
# USB host-controller driver
SRC_C += $(addprefix usb/host/, ehci-hcd.c)
# common
SRC_C += usb/common/common.c
# USB hid
SRC_C += $(addprefix hid/usbhid/, hid-core.c hid-quirks.c)
SRC_C += $(addprefix hid/, hid-core.c hid-generic.c hid-input.c \
hid-cherry.c hid-microsoft.c hid-multitouch.c)
hid-cherry.c hid-microsoft.c hid-multitouch.c \
wacom_sys.c wacom_wac.c)
SRC_C += $(addprefix input/, evdev.c input.c input-mt.c)
SRC_C += $(addprefix input/, tablet/wacom_sys.c tablet/wacom_wac.c)
# USB storage
SRC_C += $(addprefix usb/storage/,scsiglue.c protocol.c transport.c usb.c \
@ -59,46 +68,14 @@ SRC_C += $(addprefix usb/storage/,scsiglue.c protocol.c transport.c usb.c \
# SCSI
SRC_C += $(addprefix scsi/,scsi.c constants.c)
#
# Determine the header files included by the contrib code. For each
# of these header files we create a symlink to 'lx_emul.h'.
#
GEN_INCLUDES := $(shell grep -rh "^\#include .*\/" $(LX_CONTRIB_DIR) |\
sed "s/^\#include [^<\"]*[<\"]\([^>\"]*\)[>\"].*/\1/" | sort | uniq)
#
# Filter out original Linux headers that exist in the contrib directory
#
NO_GEN_INCLUDES := $(shell cd $(LX_CONTRIB_DIR)/include; find -name "*.h" | sed "s/.\///" | sed "s/.*include\///")
GEN_INCLUDES := $(filter-out $(NO_GEN_INCLUDES),$(GEN_INCLUDES))
#
# Put Linux headers in 'GEN_INC' dir, since some include use "../../" paths use
# three level include hierarchy
#
GEN_INC := $(shell pwd)/include/include/include
$(shell mkdir -p $(GEN_INC))
GEN_INCLUDES := $(addprefix $(GEN_INC)/,$(GEN_INCLUDES))
INC_DIR += $(GEN_INC)
#
# Make sure to create the header symlinks prior building
#
$(SRC_C:.c=.o) $(SRC_CC:.cc=.o): $(GEN_INCLUDES)
#SRC_CC = storage.cc
#SRC_C =
#
# Add suffix, since there are two hid-core.c with the same module init function
#
hid/hid-core.o: MOD_SUFFIX="_core"
$(GEN_INCLUDES):
$(VERBOSE)mkdir -p $(dir $@)
$(VERBOSE)ln -s $(LIB_INC_DIR)/lx_emul.h $@
vpath %.c $(DRIVERS_DIR)
vpath %.c $(LIB_DIR)
vpath %.cc $(LIB_DIR)
@ -111,5 +88,6 @@ vpath %.cc $(LIB_DIR)/nic
vpath %.cc $(LIB_DIR)/raw
vpath %.c $(LIB_DIR)/raw
vpath lib/int_sqrt.c $(LX_CONTRIB_DIR)
vpath %.cc $(REP_DIR)/src/lx_kit
# vi: set ft=make :

View File

@ -0,0 +1,35 @@
ifeq ($(called_from_lib_mk),yes)
USB_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/lib/usb
LX_EMUL_H := $(REP_DIR)/src/lib/usb/include/lx_emul.h
#
# Determine the header files included by the contrib code. For each
# of these header files we create a symlink to 'lx_emul.h'.
#
GEN_INCLUDES := $(shell grep -rh "^\#include .*\/" $(USB_CONTRIB_DIR) |\
sed "s/^\#include [^<\"]*[<\"]\([^>\"]*\)[>\"].*/\1/" |\
sort | uniq)
#
# Filter out original Linux headers that exist in the contrib directory
#
NO_GEN_INCLUDES := $(shell cd $(USB_CONTRIB_DIR)/; find include -name "*.h" |\
sed "s/.\///" | sed "s/.*include\///")
GEN_INCLUDES := $(filter-out $(NO_GEN_INCLUDES),$(GEN_INCLUDES))
#
# Put Linux headers in 'GEN_INC' dir, since some include use "../../" paths use
# three level include hierarchy
#
GEN_INC := $(shell pwd)/include/include/include
GEN_INCLUDES := $(addprefix $(GEN_INC)/,$(GEN_INCLUDES))
all: $(GEN_INCLUDES)
$(GEN_INCLUDES):
$(VERBOSE)mkdir -p $(dir $@)
$(VERBOSE)ln -s $(LX_EMUL_H) $@
endif
# vi: set ft=make :

View File

@ -1,12 +1,8 @@
commit 5151dad7cc61bf2b4527c56bd0dffcea2da25905
Author: Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
Date: Mon Jun 2 13:23:44 2014 +0200
ax88179_178a.patch
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
index e6338c1..b768fc8 100644
--- a/drivers/net/usb/ax88179_178a.c
+++ b/drivers/net/usb/ax88179_178a.c
@@ -1019,6 +1019,7 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf)
@@ -1266,6 +1266,7 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf)
dev->net->netdev_ops = &ax88179_netdev_ops;
dev->net->ethtool_ops = &ax88179_ethtool_ops;
dev->net->needed_headroom = 8;

View File

@ -1,12 +1,8 @@
commit e3804842c60157bab0d5bf2daa42f99ec3f8499d
Author: Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
Date: Mon Jun 2 13:24:37 2014 +0200
csum.patch
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 66b3ab9..a17f054 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -1716,7 +1716,13 @@ static int smsc95xx_resume(struct usb_interface *intf)
@@ -1730,7 +1730,13 @@ static int smsc95xx_reset_resume(struct usb_interface *intf)
static void smsc95xx_rx_csum_offload(struct sk_buff *skb)
{

View File

@ -1,12 +1,8 @@
commit a30968815ec1e4967a6c531744b2788f2c25e675
Author: Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
Date: Mon Jun 2 13:25:03 2014 +0200
evdev.patch
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index e9ae3d5..edd0b4f 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -1168,6 +1168,9 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
@@ -1425,6 +1425,9 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
if (error)
goto err_cleanup_evdev;
@ -16,7 +12,7 @@ Date: Mon Jun 2 13:25:03 2014 +0200
return 0;
err_cleanup_evdev:
@@ -1200,8 +1203,7 @@ static const struct input_device_id evdev_ids[] = {
@@ -1457,8 +1460,7 @@ static const struct input_device_id evdev_ids[] = {
MODULE_DEVICE_TABLE(input, evdev_ids);
static struct input_handler evdev_handler = {

View File

@ -1,180 +1,137 @@
commit 91eb4a3e68978feca81f6a5bc31cfcd7c683d628
Author: Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
Date: Tue Mar 15 09:59:11 2016 +0100
mem
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 44df131..0d0aa68 100644
index 5dd426f..6b4294a 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -840,7 +840,7 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
@@ -841,7 +841,7 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
&usbhid->inbuf_dma);
usbhid->outbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL,
&usbhid->outbuf_dma);
- usbhid->cr = kmalloc(sizeof(*usbhid->cr), GFP_KERNEL);
+ usbhid->cr = kmalloc(sizeof(*usbhid->cr), GFP_NOIO);
+ usbhid->cr = kmalloc(sizeof(*usbhid->cr), GFP_LX_DMA);
usbhid->ctrlbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL,
&usbhid->ctrlbuf_dma);
if (!usbhid->inbuf || !usbhid->outbuf || !usbhid->cr ||
@@ -998,7 +998,7 @@ static int usbhid_parse(struct hid_device *hid)
@@ -1013,7 +1013,7 @@ static int usbhid_parse(struct hid_device *hid)
return -EINVAL;
}
- if (!(rdesc = kmalloc(rsize, GFP_KERNEL))) {
+ if (!(rdesc = kmalloc(rsize, GFP_NOIO))) {
+ if (!(rdesc = kmalloc(rsize, GFP_LX_DMA))) {
dbg_hid("couldn't allocate rdesc memory\n");
return -ENOMEM;
}
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index f9e96c4..31d8b12 100644
index 0744bf2..6237370 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -228,7 +228,7 @@ static int init_status (struct usbnet *dev, struct usb_interface *intf)
@@ -229,7 +229,7 @@ static int init_status (struct usbnet *dev, struct usb_interface *intf)
period = max ((int) dev->status->desc.bInterval,
(dev->udev->speed == USB_SPEED_HIGH) ? 7 : 3);
- buf = kmalloc (maxp, GFP_KERNEL);
+ buf = kmalloc (maxp, GFP_NOIO);
+ buf = kmalloc (maxp, GFP_LX_DMA);
if (buf) {
dev->interrupt = usb_alloc_urb (0, GFP_KERNEL);
if (!dev->interrupt) {
@@ -1772,7 +1772,7 @@ int usbnet_resume (struct usb_interface *intf)
if (!--dev->suspend_count) {
/* resume interrupt URB if it was previously submitted */
- __usbnet_status_start_force(dev, GFP_NOIO);
+ __usbnet_status_start_force(dev, GFP_KERNEL);
spin_lock_irq(&dev->txq.lock);
while ((res = usb_get_from_anchor(&dev->deferred))) {
@@ -1801,7 +1801,7 @@ int usbnet_resume (struct usb_interface *intf)
if (netif_device_present(dev->net) &&
!timer_pending(&dev->delay) &&
!test_bit(EVENT_RX_HALT, &dev->flags))
- rx_alloc_submit(dev, GFP_NOIO);
+ rx_alloc_submit(dev, GFP_KERNEL);
if (!(dev->txq.qlen >= TX_QLEN(dev)))
netif_tx_wake_all_queues(dev->net);
@@ -1867,7 +1867,7 @@ static int __usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
@@ -1916,7 +1916,7 @@ static int __usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
cmd, reqtype, value, index, size);
if (data) {
- buf = kmalloc(size, GFP_KERNEL);
+ buf = kmalloc(size, GFP_NOIO);
+ buf = kmalloc(size, GFP_LX_DMA);
if (!buf)
goto out;
}
@@ -1894,7 +1894,7 @@ static int __usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
@@ -1943,7 +1943,7 @@ static int __usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
cmd, reqtype, value, index, size);
if (data) {
- buf = kmemdup(data, size, GFP_KERNEL);
+ buf = kmemdup(data, size, GFP_NOIO);
+ buf = kmemdup(data, size, GFP_LX_DMA);
if (!buf)
goto out;
}
@@ -2006,7 +2006,7 @@ int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
@@ -2192,7 +2192,7 @@ int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
}
if (data) {
- buf = kmemdup(data, size, GFP_ATOMIC);
+ buf = kmemdup(data, size, GFP_NOIO);
+ buf = kmemdup(data, size, GFP_LX_DMA);
if (!buf) {
netdev_err(dev->net, "Error allocating buffer"
" in %s!\n", __func__);
@@ -2014,7 +2014,7 @@ int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
@@ -2200,7 +2200,7 @@ int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
}
}
- req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
+ req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
+ req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_LX_DMA);
if (!req)
goto fail_free_buf;
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 062967c..f5da439 100644
index 5050760..9ac55f9 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -683,7 +683,7 @@ int usb_get_configuration(struct usb_device *dev)
@@ -695,7 +695,7 @@ int usb_get_configuration(struct usb_device *dev)
if (!dev->rawdescriptors)
goto err2;
- desc = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);
+ desc = kmalloc(USB_DT_CONFIG_SIZE, GFP_NOIO);
+ desc = kmalloc(USB_DT_CONFIG_SIZE, GFP_LX_DMA);
if (!desc)
goto err2;
@@ -712,7 +712,7 @@ int usb_get_configuration(struct usb_device *dev)
@@ -724,7 +724,7 @@ int usb_get_configuration(struct usb_device *dev)
USB_DT_CONFIG_SIZE);
/* Now that we know the length, get the whole thing */
- bigbuffer = kmalloc(length, GFP_KERNEL);
+ bigbuffer = kmalloc(length, GFP_NOIO);
+ bigbuffer = kmalloc(length, GFP_LX_DMA);
if (!bigbuffer) {
result = -ENOMEM;
goto err;
@@ -774,7 +774,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
@@ -786,7 +786,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
int length, total_len, num, i;
int ret;
- bos = kzalloc(sizeof(struct usb_bos_descriptor), GFP_KERNEL);
+ bos = kzalloc(sizeof(struct usb_bos_descriptor), GFP_NOIO);
+ bos = kzalloc(sizeof(struct usb_bos_descriptor), GFP_LX_DMA);
if (!bos)
return -ENOMEM;
@@ -800,7 +800,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
@@ -812,7 +812,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
return -ENOMEM;
/* Now let's get the whole BOS descriptor set */
- buffer = kzalloc(total_len, GFP_KERNEL);
+ buffer = kzalloc(total_len, GFP_NOIO);
+ buffer = kzalloc(total_len, GFP_LX_DMA);
if (!buffer) {
ret = -ENOMEM;
goto err;
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index 2a3bbdf..c78eedd 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -513,7 +513,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
return 0;
/* allocate 2^1 pages = 8K (on i386);
* should be more than enough for one device */
- pages_start = (char *)__get_free_pages(GFP_NOIO, 1);
+ pages_start = (char *)__get_free_pages(GFP_KERNEL, 1);
if (!pages_start)
return -ENOMEM;
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index d498d03..87b0b6b 100644
index 1560f3f..54e99b5 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1056,7 +1056,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
hcd = bus_to_hcd(hdev->bus);
if (hcd->driver->update_hub_device) {
ret = hcd->driver->update_hub_device(hcd, hdev,
- &hub->tt, GFP_NOIO);
+ &hub->tt, GFP_KERNEL);
if (ret < 0) {
dev_err(hub->intfdev, "Host not "
"accepting hub info "
@@ -1205,7 +1205,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
init3:
hub->quiescing = 0;
- status = usb_submit_urb(hub->urb, GFP_NOIO);
+ status = usb_submit_urb(hub->urb, GFP_KERNEL);
if (status < 0)
dev_err(hub->intfdev, "activate --> %d\n", status);
if (hub->has_indicators && blinkenlights)
@@ -1296,20 +1296,20 @@ static int hub_configure(struct usb_hub *hub,
unsigned unit_load;
@@ -1365,20 +1365,20 @@ static int hub_configure(struct usb_hub *hub,
unsigned full_load;
unsigned maxchild;
- hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_KERNEL);
+ hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_NOIO);
+ hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_LX_DMA);
if (!hub->buffer) {
ret = -ENOMEM;
goto fail;
}
- hub->status = kmalloc(sizeof(*hub->status), GFP_KERNEL);
+ hub->status = kmalloc(sizeof(*hub->status), GFP_NOIO);
+ hub->status = kmalloc(sizeof(*hub->status), GFP_LX_DMA);
if (!hub->status) {
ret = -ENOMEM;
goto fail;
@ -182,105 +139,34 @@ index d498d03..87b0b6b 100644
mutex_init(&hub->status_mutex);
- hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL);
+ hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_NOIO);
+ hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_LX_DMA);
if (!hub->descriptor) {
ret = -ENOMEM;
goto fail;
@@ -3464,9 +3464,9 @@ static int usb_req_set_sel(struct usb_device *udev, enum usb3_link_state state)
/*
* usb_enable_lpm() can be called as part of a failed device reset,
* which may be initiated by an error path of a mass storage driver.
- * Therefore, use GFP_NOIO.
+ * Therefore, use GFP_KERNEL.
*/
- sel_values = kmalloc(sizeof *(sel_values), GFP_NOIO);
+ sel_values = kmalloc(sizeof *(sel_values), GFP_KERNEL);
if (!sel_values)
return -ENOMEM;
@@ -4586,7 +4586,7 @@ check_highspeed(struct usb_hub *hub, struct usb_device *udev, int port1)
if (udev->quirks & USB_QUIRK_DEVICE_QUALIFIER)
return;
@@ -4299,7 +4299,7 @@ check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1)
struct usb_qualifier_descriptor *qual;
int status;
- qual = kmalloc (sizeof *qual, GFP_KERNEL);
+ qual = kmalloc (sizeof *qual, GFP_NOIO);
- qual = kmalloc(sizeof *qual, GFP_KERNEL);
+ qual = kmalloc(sizeof *qual, GFP_LX_DMA);
if (qual == NULL)
return;
@@ -5030,7 +5030,7 @@ static int descriptors_changed(struct usb_device *udev,
len = max(len, old_length);
}
- buf = kmalloc(len, GFP_NOIO);
+ buf = kmalloc(len, GFP_KERNEL);
if (buf == NULL) {
dev_err(&udev->dev, "no mem to re-read configs after reset\n");
/* assume the worst */
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index f829a1a..91aa41a 100644
index 8e641b5..5807f68 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -49,7 +49,7 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
init_completion(&ctx.done);
urb->context = &ctx;
urb->actual_length = 0;
- retval = usb_submit_urb(urb, GFP_NOIO);
+ retval = usb_submit_urb(urb, GFP_KERNEL);
if (unlikely(retval))
goto out;
@@ -86,7 +86,7 @@ static int usb_internal_control_msg(struct usb_device *usb_dev,
int retv;
int length;
- urb = usb_alloc_urb(0, GFP_NOIO);
+ urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb)
return -ENOMEM;
@@ -869,11 +869,11 @@ char *usb_cache_string(struct usb_device *udev, int index)
if (index <= 0)
return NULL;
- buf = kmalloc(MAX_USB_STRING_SIZE, GFP_NOIO);
+ buf = kmalloc(MAX_USB_STRING_SIZE, GFP_KERNEL);
if (buf) {
len = usb_string(udev, index, buf, MAX_USB_STRING_SIZE);
if (len > 0) {
- smallbuf = kmalloc(++len, GFP_NOIO);
+ smallbuf = kmalloc(++len, GFP_KERNEL);
if (!smallbuf)
return buf;
memcpy(smallbuf, buf, len);
@@ -944,7 +944,7 @@ int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)
@@ -942,7 +942,7 @@ int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)
int usb_get_status(struct usb_device *dev, int type, int target, void *data)
{
int ret;
- __le16 *status = kmalloc(sizeof(*status), GFP_KERNEL);
+ __le16 *status = kmalloc(sizeof(*status), GFP_NOIO);
+ __le16 *status = kmalloc(sizeof(*status), GFP_LX_DMA);
if (!status)
return -ENOMEM;
@@ -1743,7 +1743,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
if (cp) {
nintf = cp->desc.bNumInterfaces;
new_interfaces = kmalloc(nintf * sizeof(*new_interfaces),
- GFP_NOIO);
+ GFP_KERNEL);
if (!new_interfaces) {
dev_err(&dev->dev, "Out of memory\n");
return -ENOMEM;
@@ -1752,7 +1752,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
for (; n < nintf; ++n) {
new_interfaces[n] = kzalloc(
sizeof(struct usb_interface),
- GFP_NOIO);
+ GFP_KERNEL);
if (!new_interfaces[n]) {
dev_err(&dev->dev, "Out of memory\n");
ret = -ENOMEM;
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index c0fb6a8..107f41d 100644
index b6205fa..99cae0f 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -82,7 +82,7 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags)
@ -288,104 +174,154 @@ index c0fb6a8..107f41d 100644
dma_addr_t dma;
- qh = kzalloc(sizeof *qh, GFP_ATOMIC);
+ qh = kzalloc(sizeof *qh, GFP_NOIO);
+ qh = kzalloc(sizeof *qh, GFP_LX_DMA);
if (!qh)
goto done;
qh->hw = (struct ehci_qh_hw *)
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 9992fbf..10f539c 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -276,7 +276,7 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
ret = 0;
virt_dev = xhci->devs[slot_id];
- cmd = xhci_alloc_command(xhci, false, true, GFP_NOIO);
+ cmd = xhci_alloc_command(xhci, false, true, GFP_KERNEL);
if (!cmd) {
xhci_dbg(xhci, "Couldn't allocate command structure.\n");
return -ENOMEM;
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index cca2896..9b5c07e 100644
index 776d59c..e32db7b 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1279,7 +1279,7 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
@@ -1354,7 +1354,7 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
size = 1;
urb_priv = kzalloc(sizeof(struct urb_priv) +
- size * sizeof(struct xhci_td *), mem_flags);
+ size * sizeof(struct xhci_td *), GFP_NOIO);
+ size * sizeof(struct xhci_td *), GFP_LX_DMA);
if (!urb_priv)
return -ENOMEM;
@@ -1722,7 +1722,7 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
* process context, not interrupt context (or so documenation
* for usb_set_interface() and usb_set_configuration() claim).
*/
- if (xhci_endpoint_init(xhci, virt_dev, udev, ep, GFP_NOIO) < 0) {
+ if (xhci_endpoint_init(xhci, virt_dev, udev, ep, GFP_KERNEL) < 0) {
dev_dbg(&udev->dev, "%s - could not initialize ep %#x\n",
__func__, ep->desc.bEndpointAddress);
return -ENOMEM;
@@ -3435,10 +3435,10 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
/* Allocate the command structure that holds the struct completion.
* Assume we're in process context, since the normal device reset
* process has to wait for the device anyway. Storage devices are
- * reset as part of error handling, so use GFP_NOIO instead of
+ * reset as part of error handling, so use GFP_KERNEL instead of
* GFP_KERNEL.
*/
- reset_device_cmd = xhci_alloc_command(xhci, false, true, GFP_NOIO);
+ reset_device_cmd = xhci_alloc_command(xhci, false, true, GFP_KERNEL);
if (!reset_device_cmd) {
xhci_dbg(xhci, "Couldn't allocate command structure.\n");
return -ENOMEM;
@@ -3682,11 +3682,11 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
}
spin_unlock_irqrestore(&xhci->lock, flags);
}
- /* Use GFP_NOIO, since this function can be called from
+ /* Use GFP_KERNEL, since this function can be called from
* xhci_discover_or_reset_device(), which may be called as part of
* mass storage driver error handling.
*/
- if (!xhci_alloc_virt_device(xhci, xhci->slot_id, udev, GFP_NOIO)) {
+ if (!xhci_alloc_virt_device(xhci, xhci->slot_id, udev, GFP_KERNEL)) {
xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n");
goto disable_slot;
}
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 22c7d43..783f745 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -151,7 +151,7 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
us->current_urb->transfer_dma = us->iobuf_dma;
/* submit the URB */
- status = usb_submit_urb(us->current_urb, GFP_NOIO);
+ status = usb_submit_urb(us->current_urb, GFP_KERNEL);
if (status) {
/* something went wrong */
return status;
@@ -427,7 +427,7 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
/* initialize the scatter-gather request block */
usb_stor_dbg(us, "xfer %u bytes, %d entries\n", length, num_sg);
result = usb_sg_init(&us->current_sg, us->pusb_dev, pipe, 0,
- sg, num_sg, length, GFP_NOIO);
+ sg, num_sg, length, GFP_KERNEL);
if (result) {
usb_stor_dbg(us, "usb_sg_init returned %d\n", result);
return USB_STOR_XFER_ERROR;
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 1c0b89f..e34e087 100644
index 43576ed..2b13b4e 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -442,7 +442,7 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf)
@@ -450,7 +450,7 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf)
usb_set_intfdata(intf, us);
/* Allocate the control/setup and DMA-mapped buffers */
- us->cr = kmalloc(sizeof(*us->cr), GFP_KERNEL);
+ us->cr = kmalloc(sizeof(*us->cr), GFP_NOIO);
+ us->cr = kmalloc(sizeof(*us->cr), GFP_LX_DMA);
if (!us->cr)
return -ENOMEM;
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -325,7 +325,7 @@
if (td->mtclass.name != MT_CLS_WIN_8)
return;
- buf = hid_alloc_report_buf(report, GFP_KERNEL);
+ buf = hid_alloc_report_buf(report, GFP_LX_DMA);
if (!buf)
return;
@@ -912,7 +912,7 @@
if (r) {
if (cls->quirks & MT_QUIRK_FORCE_GET_FEATURE) {
report_len = hid_report_len(r);
- buf = hid_alloc_report_buf(r, GFP_KERNEL);
+ buf = hid_alloc_report_buf(r, GFP_LX_DMA);
if (!buf) {
hid_err(hdev, "failed to allocate buffer for report\n");
return;
@@ -1043,7 +1043,7 @@
if (suffix) {
name = devm_kzalloc(&hi->input->dev,
strlen(hdev->name) + strlen(suffix) + 2,
- GFP_KERNEL);
+ GFP_LX_DMA);
if (name) {
sprintf(name, "%s %s", hdev->name, suffix);
hi->input->name = name;
@@ -1096,7 +1096,7 @@
*/
hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
- td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_KERNEL);
+ td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_LX_DMA);
if (!td) {
dev_err(&hdev->dev, "cannot allocate multitouch data\n");
return -ENOMEM;
@@ -1110,7 +1110,7 @@
hid_set_drvdata(hdev, td);
td->fields = devm_kzalloc(&hdev->dev, sizeof(struct mt_fields),
- GFP_KERNEL);
+ GFP_LX_DMA);
if (!td->fields) {
dev_err(&hdev->dev, "cannot allocate multitouch fields data\n");
return -ENOMEM;
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -124,7 +124,7 @@
/* leave touch_max as is if predefined */
if (!features->touch_max) {
/* read manually */
- data = kzalloc(2, GFP_KERNEL);
+ data = kzalloc(2, GFP_LX_DMA);
if (!data)
break;
data[0] = field->report->id;
@@ -328,7 +328,7 @@
unsigned char *rep_data;
int error = -ENOMEM, limit = 0;
- rep_data = kzalloc(length, GFP_KERNEL);
+ rep_data = kzalloc(length, GFP_LX_DMA);
if (!rep_data)
return error;
@@ -530,7 +530,7 @@
data = wacom_get_hdev_data(hdev);
if (!data) {
- data = kzalloc(sizeof(struct wacom_hdev_data), GFP_KERNEL);
+ data = kzalloc(sizeof(struct wacom_hdev_data), GFP_LX_DMA);
if (!data) {
retval = -ENOMEM;
goto out;
@@ -595,7 +595,7 @@
report_id = WAC_CMD_WL_LED_CONTROL;
buf_size = 13;
}
- buf = kzalloc(buf_size, GFP_KERNEL);
+ buf = kzalloc(buf_size, GFP_LX_DMA);
if (!buf)
return -ENOMEM;
@@ -648,7 +648,7 @@
int i, retval;
const unsigned chunk_len = len / 4; /* 4 chunks are needed to be sent */
- buf = kzalloc(chunk_len + 3 , GFP_KERNEL);
+ buf = kzalloc(chunk_len + 3 , GFP_LX_DMA);
if (!buf)
return -ENOMEM;
@@ -1176,7 +1176,7 @@
wacom_wac->serial[index] = serial;
- buf = kzalloc(WAC_REMOTE_SERIAL_MAX_STRLEN, GFP_KERNEL);
+ buf = kzalloc(WAC_REMOTE_SERIAL_MAX_STRLEN, GFP_LX_DMA);
if (!buf)
return -ENOMEM;
snprintf(buf, WAC_REMOTE_SERIAL_MAX_STRLEN, "%d", serial);
@@ -1222,7 +1222,7 @@
unsigned char *buf;
int retval;
- buf = kzalloc(buf_size, GFP_KERNEL);
+ buf = kzalloc(buf_size, GFP_LX_DMA);
if (!buf)
return -ENOMEM;
@@ -1705,7 +1705,7 @@
/* hid-core sets this quirk for the boot interface */
hdev->quirks &= ~HID_QUIRK_NOGET;
- wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
+ wacom = kzalloc(sizeof(struct wacom), GFP_LX_DMA);
if (!wacom)
return -ENOMEM;

View File

@ -1,12 +1,8 @@
commit e500c61c5fce23cf3a44bdd45fded0a3f34cf4f0
Author: Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
Date: Mon Jun 2 13:35:56 2014 +0200
usbnet.patch
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 6237370..8339402 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -63,8 +63,30 @@
@@ -64,8 +64,30 @@
* the equation.
*/
#define MAX_QUEUE_MEMORY (60 * 1518)

View File

@ -1,181 +0,0 @@
From aa61126013bd3f9bb41e5256e4246bc0c5bf348d Mon Sep 17 00:00:00 2001
From: Jason Gerecke <killertofu@gmail.com>
Date: Tue, 6 May 2014 17:14:59 -0700
Subject: [PATCH] Add support for 056a:5002 (Fujitsu T904)
The 5002 appears to use a standard multitouch packet type, but the
pen packet has a new report ID.
Signed-off-by: Jason Gerecke <killertofu@gmail.com>
---
drivers/input/tablet/wacom_sys.c | 19 +++++++++++++++++++
drivers/input/tablet/wacom_wac.c | 12 +++++++++++-
drivers/input/tablet/wacom_wac.h | 3 +++
3 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index b16ebef..0056a6d 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -364,6 +364,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
break;
case MTTPC:
+ case MTTPC_B:
features->pktlen = WACOM_PKGLEN_MTTPC;
break;
@@ -395,6 +396,16 @@ static int wacom_parse_hid(struct usb_interface *intf,
i += 12;
break;
+ case MTTPC_B:
+ features->x_max =
+ get_unaligned_le16(&report[i + 3]);
+ features->x_phy =
+ get_unaligned_le16(&report[i + 6]);
+ features->unit = report[i - 5];
+ features->unitExpo = report[i - 3];
+ i += 9;
+ break;
+
default:
features->x_max =
get_unaligned_le16(&report[i + 3]);
@@ -447,6 +458,14 @@ static int wacom_parse_hid(struct usb_interface *intf,
i += 12;
break;
+ case MTTPC_B:
+ features->y_max =
+ get_unaligned_le16(&report[i + 3]);
+ features->y_phy =
+ get_unaligned_le16(&report[i + 6]);
+ i += 9;
+ break;
+
default:
features->y_max =
features->x_max;
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 05f371d..9330e17 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -966,7 +966,7 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
int x_offset = 0;
/* MTTPC does not support Height and Width */
- if (wacom->features.type == MTTPC)
+ if (wacom->features.type == MTTPC || wacom->features.type == MTTPC_B)
x_offset = -4;
/*
@@ -1119,6 +1119,9 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
case WACOM_PKGLEN_TPC2FG:
return wacom_tpc_mt_touch(wacom);
+ case WACOM_PKGLEN_PENABLED:
+ return wacom_tpc_pen(wacom);
+
default:
switch (data[0]) {
case WACOM_REPORT_TPC1FG:
@@ -1128,6 +1131,7 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
return wacom_tpc_single_touch(wacom, len);
case WACOM_REPORT_TPCMT:
+ case WACOM_REPORT_TPCMT2:
return wacom_mt_touch(wacom);
case WACOM_REPORT_PENABLED:
@@ -1470,6 +1474,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
case TABLETPC2FG:
case MTSCREEN:
case MTTPC:
+ case MTTPC_B:
sync = wacom_tpc_irq(wacom_wac, len);
break;
@@ -1811,6 +1816,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
case MTSCREEN:
case MTTPC:
+ case MTTPC_B:
case TABLETPC2FG:
if (features->device_type == BTN_TOOL_FINGER) {
unsigned int flags = INPUT_MT_DIRECT;
@@ -2245,6 +2251,9 @@ static const struct wacom_features wacom_features_0x10F =
static const struct wacom_features wacom_features_0x4001 =
{ "Wacom ISDv4 4001", WACOM_PKGLEN_MTTPC, 26202, 16325, 255,
0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x5002 =
+ { "Wacom ISDv4 5002", WACOM_PKGLEN_MTTPC, 29576, 16724, 1023,
+ 0, MTTPC_B, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x47 =
{ "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023,
31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -2466,6 +2475,7 @@ const struct usb_device_id wacom_ids[] = {
{ USB_DEVICE_DETAILED(0x315, USB_CLASS_HID, 0, 0) },
{ USB_DEVICE_DETAILED(0x317, USB_CLASS_HID, 0, 0) },
{ USB_DEVICE_WACOM(0x4001) },
+ { USB_DEVICE_WACOM(0x5002) },
{ USB_DEVICE_WACOM(0x47) },
{ USB_DEVICE_WACOM(0xF4) },
{ USB_DEVICE_WACOM(0xF8) },
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index f69c0eb..620dae8 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -30,6 +30,7 @@
#define WACOM_PKGLEN_MTOUCH 62
#define WACOM_PKGLEN_MTTPC 40
#define WACOM_PKGLEN_DTUS 68
+#define WACOM_PKGLEN_PENABLED 8
/* wacom data size per MT contact */
#define WACOM_BYTES_PER_MT_PACKET 11
@@ -52,6 +53,7 @@
#define WACOM_REPORT_TPC1FG 6
#define WACOM_REPORT_TPC2FG 13
#define WACOM_REPORT_TPCMT 13
+#define WACOM_REPORT_TPCMT2 3
#define WACOM_REPORT_TPCHID 15
#define WACOM_REPORT_TPCST 16
#define WACOM_REPORT_DTUS 17
@@ -105,6 +107,7 @@ enum {
TABLETPC2FG,
MTSCREEN,
MTTPC,
+ MTTPC_B,
MAX_TYPE
};
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -246,7 +248,7 @@
int result = 0;
unsigned char *rep_data;
- rep_data = kmalloc(2, GFP_KERNEL);
+ rep_data = kmalloc(2, GFP_NOIO);
if (rep_data) {
rep_data[0] = 12;
@@ -308,7 +310,7 @@
int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0;
unsigned char *report;
- report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL);
+ report = kzalloc(hid_desc->wDescriptorLength, GFP_NOIO);
if (!report)
return -ENOMEM;
@@ -517,7 +538,7 @@
unsigned char *rep_data;
int error = -ENOMEM, limit = 0;
- rep_data = kzalloc(length, GFP_KERNEL);
+ rep_data = kzalloc(length, GFP_NOIO);
if (!rep_data)
return error;

View File

@ -1,28 +0,0 @@
commit 00c1504c478a364d74cf9720643a57d9fd180a6b
Author: Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
Date: Mon Jun 2 13:36:46 2014 +0200
xhci-quirks.patch
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -38,6 +38,8 @@
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI 0x8c31
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31
+#define PCI_VENDOR_ID_RENESAS 0x1912
+
static const char hcd_name[] = "xhci_hcd";
/* called after powerup, by probe or system-pm "wakeup" */
@@ -95,6 +97,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
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;

View File

@ -1,14 +0,0 @@
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -688,6 +688,11 @@
{
struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index];
+ if (!deq_state->new_deq_seg) {
+ deq_state->new_deq_ptr = 0;
+ return;
+ }
+
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
"Set TR Deq Ptr cmd, new deq seg = %p (0x%llx dma), "
"new deq ptr = %p (0x%llx dma), new cycle = %u",

View File

@ -1 +1 @@
9f095930834c35a2dfc8eaf58b6905081f206c34
c63f9c4df89a087251bafa448b8fd99f04334564

View File

@ -14,6 +14,12 @@ $(call check_tool,bison)
FLEX = flex
YACC = bison
#
# The git checkout checks for the existence of SRC_DIR, which is created by the
# Linux extraction, therefore make sure to checkout the GIT sources first.
#
usb.archive: dwc_otg.git
#
# The git checkout checks for the existence of SRC_DIR, which is created by the
@ -25,9 +31,9 @@ usb.archive: dwc_otg.git
# USB
#
SRC_DIR_USB := src/lib/usb
VERSION_USB := 3.14.5
URL(usb) := http://www.kernel.org/pub/linux/kernel/v3.x/linux-$(VERSION_USB).tar.gz
SHA(usb) := 675bb3446cbf0889d59a048f6af177ca0a7aacb5
VERSION_USB := 4.4.3
URL(usb) := http://www.kernel.org/pub/linux/kernel/v4.x/linux-$(VERSION_USB).tar.xz
SHA(usb) := 336d66925a15ce9077cbf2c38acbdc6c2644e33f
DIR(usb) := $(SRC_DIR_USB)
TAR_OPT(usb) := --strip-components=1 --files-from $(REP_DIR)/usb.list
HASH_INPUT += $(REP_DIR)/usb.list
@ -35,8 +41,8 @@ HASH_INPUT += $(REP_DIR)/usb.list
#
# Raspberry Pi USB controller
#
URL(dwc_otg) := https://github.com/nfeske/dwc_otg.git
REV(dwc_otg) := r2
URL(dwc_otg) := https://github.com/ssumpf/dwc_otg.git
REV(dwc_otg) := r3
DIR(dwc_otg) := $(SRC_DIR_USB)/drivers/usb/host/dwc_otg
@ -44,8 +50,9 @@ DIR(dwc_otg) := $(SRC_DIR_USB)/drivers/usb/host/dwc_otg
# Intel framebuffer driver
#
SRC_DIR_INTEL_FB := src/drivers/framebuffer/intel
URL(intel_fb) := ${URL(usb)}
SHA(intel_fb) := ${SHA(usb)}
VERSION_INTEL_FB := 3.14.5
URL(intel_fb) := http://www.kernel.org/pub/linux/kernel/v3.x/linux-$(VERSION_INTEL_FB).tar.gz
SHA(intel_fb) := 675bb3446cbf0889d59a048f6af177ca0a7aacb5
DIR(intel_fb) := $(SRC_DIR_INTEL_FB)
TAR_OPT(intel_fb) := --strip-components=1 --files-from $(REP_DIR)/intel_fb.list
HASH_INPUT += $(REP_DIR)/intel_fb.list
@ -189,8 +196,5 @@ PATCH_OPT(patches/usb_csum.patch) := $(USB_OPT)
PATCH_OPT(patches/usb_evdev.patch) := $(USB_OPT)
PATCH_OPT(patches/usb_mem.patch) := $(USB_OPT)
PATCH_OPT(patches/usb_usbnet.patch) := $(USB_OPT)
PATCH_OPT(patches/usb_xchi-quirks.patch) := $(USB_OPT)
PATCH_OPT(patches/usb_wacom.patch) := $(USB_OPT)
PATCH_OPT(patches/usb_xhci-ring.patch) := $(USB_OPT)
# vi: set ft=make :

View File

@ -54,7 +54,7 @@ append config {
<provides><service name="Timer"/></provides>
</start>
<start name="usb_drv">
<resource name="RAM" quantum="10M"/>
<resource name="RAM" quantum="16M"/>
<provides><service name="Input"/></provides>
<config uhci="yes" ehci="yes" xhci="yes">
<hid/>

View File

@ -67,6 +67,7 @@ append config {
<start name="test-usb">
<resource name="RAM" quantum="2M" />
<binary name="test-blk-cli" />
<config test_size="1M" />
</start>
</config>
}
@ -100,18 +101,27 @@ catch { exec sh -c $cmd }
#
# Qemu opts for UHCI
#
#append qemu_args " -m 64 -nographic -usbdevice disk::$disk_image -boot order=d"
#append qemu_args " -m 128 -nographic -usbdevice disk::$disk_image -boot order=d"
#
# Qemu opts for EHCI
#
append qemu_args "-drive if=none,id=disk,file=$disk_image,format=raw"
append qemu_args "-drive if=none,id=disk,file=$disk_image"
append qemu_args { \
-m 128 -nographic -M pc \
-device usb-ehci,id=ehci \
-device usb-storage,bus=ehci.0,drive=disk \
-boot order=d }
#
# Qemu opts for XHCI
#
#append qemu_args { \
#-m 128 -nographic -M pc \
#-device nec-usb-xhci,id=xhci \
#-device usb-storage,bus=xhci.0,drive=disk \
#-boot order=d }
run_genode_until {.*child "test-usb" exited with exit value 0.*} 100
puts "\nTest succeeded\n"

View File

@ -51,5 +51,7 @@ struct kobj_uevent_env
struct kobj_uevent_env;
int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...);
void kobject_put(struct kobject *);
char *kobject_name(const struct kobject *kobj);
char *kobject_get_path(struct kobject *kobj, gfp_t gfp_mask);
struct kobject * kobject_create_and_add(const char *, struct kobject *);

View File

@ -32,6 +32,12 @@
#define SKIP
#endif
/******************
** linux/slab.h **
******************/
void *kmalloc_array(size_t n, size_t size, gfp_t flags) { TRACE; return (void *)0xdeadbeaf; }
/******************
** asm/atomic.h **
@ -40,13 +46,6 @@
int atomic_inc_return(atomic_t *v) { TRACE; return 0; }
/*******************************
** linux/errno.h and friends **
*******************************/
long PTR_ERR(const void *ptr) { TRACE; return 0; }
/********************
** linux/kernel.h **
********************/
@ -55,6 +54,7 @@ void might_sleep() { SKIP; }
char *kasprintf(gfp_t gfp, const char *fmt, ...) { TRACE; return NULL; }
int kstrtouint(const char *s, unsigned int base, unsigned int *res) { TRACE; return 0; }
int kstrtoul(const char *s, unsigned int base, unsigned long *res) { TRACE; return 0; }
int kstrtou8(const char *s, unsigned int base, u8 *x) { TRACE; return 1; }
int sprintf(char *buf, const char *fmt, ...) { TRACE; return 0; }
int sscanf(const char *b, const char *s, ...) { TRACE; return 0; }
int scnprintf(char *buf, size_t size, const char *fmt, ...);
@ -76,8 +76,8 @@ int roundup_pow_of_two(u32 n) { TRACE; return 0; }
void print_hex_dump(const char *level, const char *prefix_str,
int prefix_type, int rowsize, int groupsize,
const void *buf, size_t len, bool ascii) { TRACE; }
int printk_ratelimit() { TRACE; return 0; }
int printk_ratelimited() { TRACE; return 0; }
bool printk_ratelimit() { TRACE; return 0; }
bool printk_ratelimited() { TRACE; return 0; }
bool printk_timed_ratelimit(unsigned long *caller_jiffies,
unsigned int interval_msec) { TRACE; return false; }
@ -132,21 +132,20 @@ void assert_spin_locked(spinlock_t *lock) { TRACE;}
** linux/mutex.h **
*******************/
void mutex_lock_nested(struct mutex *lock, unsigned int subclass) { TRACE; }
int mutex_lock_interruptible(struct mutex *m) { TRACE; return 0; }
void mutex_init (struct mutex *m) { TRACE; }
void mutex_lock (struct mutex *m) { TRACE; }
void mutex_unlock(struct mutex *m) { TRACE; }
int mutex_lock_interruptible(struct mutex *m) { SKIP; return 0; }
void mutex_init (struct mutex *m) { SKIP; }
void mutex_lock (struct mutex *m) { SKIP; }
void mutex_unlock(struct mutex *m) { SKIP; }
/*******************
** linux/rwsem.h **
*******************/
void down_read(struct rw_semaphore *sem) { TRACE; }
void up_read(struct rw_semaphore *sem) { TRACE; }
void down_write(struct rw_semaphore *sem) { TRACE; }
void up_write(struct rw_semaphore *sem) { TRACE; }
void down_read(struct rw_semaphore *sem) { SKIP; }
void up_read(struct rw_semaphore *sem) { SKIP; }
void down_write(struct rw_semaphore *sem) { SKIP; }
void up_write(struct rw_semaphore *sem) { SKIP; }
/*********************
@ -173,8 +172,7 @@ ktime_t ktime_add_ns(const ktime_t kt, u64 nsec) { KTIME_RET; }
ktime_t ktime_get_monotonic_offset(void) { KTIME_RET; }
ktime_t ktime_sub(const ktime_t lhs, const ktime_t rhs) { KTIME_RET; }
ktime_t ktime_get_real(void) { TRACE; ktime_t ret; return ret; }
struct timeval ktime_to_timeval(const ktime_t kt) { TRACE; struct timeval ret; return ret; }
ktime_t ktime_get_boottime(void) { TRACE; KTIME_RET; }
s64 ktime_us_delta(const ktime_t later, const ktime_t earlier) { TRACE; return 0; };
@ -187,12 +185,18 @@ unsigned long round_jiffies(unsigned long j) { TRACE; return 1; }
void set_timer_slack(struct timer_list *time, int slack_hz) { TRACE; }
/*******************
** linux/delay.h **
*******************/
void usleep_range(unsigned long min, unsigned long max) { TRACE; }
/***********************
** linux/workquque.h **
***********************/
bool cancel_work_sync(struct work_struct *work) { TRACE; return 0; }
int cancel_delayed_work_sync(struct delayed_work *work) { TRACE; return 0; }
void destroy_workqueue(struct workqueue_struct *wq) { TRACE; }
bool flush_work(struct work_struct *work) { TRACE; return 0; }
bool flush_work_sync(struct work_struct *work) { TRACE; return 0; }
@ -223,12 +227,18 @@ void __set_current_state(int state) { TRACE; }
int signal_pending(struct task_struct *p) { TRACE; return 0; }
void schedule(void) { TRACE; }
void yield(void) { TRACE; }
void cpu_relax(void) { TRACE; udelay(1); }
signed long schedule_timeout(signed long timeout) { TRACE; return 0; }
void cpu_relax(void) { SKIP; }
struct task_struct *current;
/******************
** linux/wait.h **
******************/
void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait) { TRACE; }
/*********************
** linux/kthread.h **
*********************/
@ -271,6 +281,8 @@ int sysfs_create_link(struct kobject *kobj, struct kobject *target,
const char *name) { TRACE; return 0; }
void sysfs_remove_link(struct kobject *kobj, const char *name) { TRACE; }
int sysfs_create_files(struct kobject *kobj, const struct attribute **attr) { TRACE; return 1; }
int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp) { TRACE; return 0; }
ssize_t simple_read_from_buffer(void __user *to, size_t count,
@ -280,22 +292,24 @@ ssize_t simple_read_from_buffer(void __user *to, size_t count,
** linux/pm_runtime.h **
************************/
int pm_runtime_set_active(struct device *dev) { TRACE; return 0; }
void pm_suspend_ignore_children(struct device *dev, bool enable) { TRACE; }
void pm_runtime_enable(struct device *dev) { TRACE; }
void pm_runtime_disable(struct device *dev) { TRACE; }
void pm_runtime_allow(struct device *dev) { TRACE; }
void pm_runtime_forbid(struct device *dev) { TRACE; }
void pm_runtime_set_suspended(struct device *dev) { TRACE; }
void pm_runtime_get_noresume(struct device *dev) { TRACE; }
void pm_runtime_put_noidle(struct device *dev) { TRACE; }
void pm_runtime_use_autosuspend(struct device *dev) { TRACE; }
int pm_runtime_put_sync_autosuspend(struct device *dev) { TRACE; return 0; }
void pm_runtime_no_callbacks(struct device *dev) { TRACE; }
void pm_runtime_set_autosuspend_delay(struct device *dev, int delay) { TRACE; }
int pm_runtime_get_sync(struct device *dev) { TRACE; return 0; }
int pm_runtime_put_sync(struct device *dev) { TRACE; return 0; }
int pm_runtime_put(struct device *dev) { TRACE; return 0; }
bool pm_runtime_active(struct device *dev) { SKIP; return true; }
int pm_runtime_set_active(struct device *dev) { SKIP; return 0; }
void pm_suspend_ignore_children(struct device *dev, bool enable) { SKIP; }
void pm_runtime_enable(struct device *dev) { SKIP; }
void pm_runtime_disable(struct device *dev) { SKIP; }
void pm_runtime_allow(struct device *dev) { SKIP; }
void pm_runtime_forbid(struct device *dev) { SKIP; }
void pm_runtime_set_suspended(struct device *dev) { SKIP; }
void pm_runtime_get_noresume(struct device *dev) { SKIP; }
void pm_runtime_put_noidle(struct device *dev) { SKIP; }
void pm_runtime_use_autosuspend(struct device *dev) { SKIP; }
int pm_runtime_put_sync_autosuspend(struct device *dev) { SKIP; return 0; }
void pm_runtime_no_callbacks(struct device *dev) { SKIP; }
void pm_runtime_set_autosuspend_delay(struct device *dev, int delay) { SKIP; }
int pm_runtime_get_sync(struct device *dev) { SKIP; return 0; }
int pm_runtime_put_sync(struct device *dev) { SKIP; return 0; }
int pm_runtime_put(struct device *dev) { SKIP; return 0; }
int pm_runtime_barrier(struct device *dev) { SKIP; return 0; }
/***********************
@ -314,6 +328,9 @@ bool device_can_wakeup(struct device *dev) { TRACE; return 0; }
********************/
int dev_pm_qos_expose_flags(struct device *dev, s32 value) { TRACE; return 0; }
int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
enum dev_pm_qos_req_type type, s32 value) { TRACE; return 0; }
int dev_pm_qos_remove_request(struct dev_pm_qos_request *req) { TRACE; return 0; }
/********************
@ -373,6 +390,8 @@ int bus_register_notifier(struct bus_type *bus,
struct notifier_block *nb) { TRACE; return 0; }
int bus_unregister_notifier(struct bus_type *bus,
struct notifier_block *nb) { TRACE; return 0; }
int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data,
int (*fn)(struct device *dev, void *data)) { TRACE; return 0; }
struct class *__class_create(struct module *owner,
const char *name,
@ -530,6 +549,7 @@ bool is_highmem(void *ptr) { TRACE; return 0; }
struct zone *page_zone(const struct page *page) { TRACE; return NULL; }
int is_vmalloc_addr(const void *x) { TRACE; return 0; }
void kvfree(const void *addr) { TRACE; }
/**********************
@ -587,11 +607,8 @@ 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; }
void *pci_get_drvdata(struct pci_dev *pdev) { TRACE; return NULL; }
void pci_dev_put(struct pci_dev *dev) { TRACE; }
struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
struct pci_dev *from) { TRACE; return NULL; }
@ -613,6 +630,7 @@ 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; }
int pci_enable_msix_exact(struct pci_dev *pdef,struct msix_entry *entries, int vec) { TRACE; return -1; }
void pci_disable_msix(struct pci_dev *pdev) { TRACE; }
@ -634,7 +652,7 @@ void pci_set_master(struct pci_dev *dev) { SKIP; }
unsigned long local_irq_save(unsigned long flags) { SKIP; return 0; }
unsigned long local_irq_restore(unsigned long flags) { SKIP; return 0; }
unsigned smp_processor_id() { return 0; }
/*************************
** linux/scatterlist.h **
@ -673,6 +691,12 @@ void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) { SKIP; return 0; }
/*********************
** linux/uaccess.h **
*********************/
unsigned long clear_user(void *to, unsigned long n) { TRACE; return 0; }
/*****************
** linux/pid.h **
*****************/
@ -736,10 +760,11 @@ int match_octal(substring_t *s, int *result) { TRACE; return 0; }
/*********************
** linux/semaphore **
*********************/
void sema_init(struct semaphore *sem, int val) { TRACE; }
int down_trylock(struct semaphore *sem) { TRACE; return 0; }
int down_interruptible(struct semaphore *sem) { TRACE; return 0; }
void up(struct semaphore *sem) { TRACE; }
void sema_init(struct semaphore *sem, int val) { SKIP; }
int down_trylock(struct semaphore *sem) { SKIP; return 0; }
int down_interruptible(struct semaphore *sem) { SKIP; return 0; }
void up(struct semaphore *sem) { SKIP; }
/*******************
@ -781,8 +806,8 @@ unsigned int queue_max_hw_sectors(struct request_queue *q) { TRACE; return 0; }
** scsi/scsi_cmnd.h **
**********************/
void scsi_set_resid(struct scsi_cmnd *cmd, int resid) { TRACE; }
int scsi_get_resid(struct scsi_cmnd *cmd) { TRACE; return 0; }
void scsi_set_resid(struct scsi_cmnd *cmd, int resid) { SKIP; }
int scsi_get_resid(struct scsi_cmnd *cmd) { SKIP; return 0; }
/********************
@ -907,6 +932,15 @@ int generic_mii_ioctl(struct mii_if_info *mii_if,
struct mii_ioctl_data *if_mii(struct ifreq *rq) { TRACE; return 0; }
/***********************
** uapi/linux/mdio.h **
***********************/
u16 ethtool_adv_to_mmd_eee_adv_t(u32 adv) { TRACE; return 0; }
u32 mmd_eee_adv_to_ethtool_adv_t(u16 eee_adv) { TRACE; return 0; }
u32 mmd_eee_cap_to_ethtool_sup_t(u16 eee_cap) { TRACE; return 0; }
/*************************
** linux/etherdevice.h **
*************************/
@ -961,6 +995,8 @@ void clk_disable_unprepare(struct clk *clk) { TRACE; }
int bitmap_subset(const unsigned long *src1,
const unsigned long *src2, int nbits) { TRACE; return 1; }
int bitmap_weight(const unsigned long *src, unsigned int nbits) { TRACE; return 0; }
/*****************
** linux/idr.h **
@ -1013,8 +1049,11 @@ u16 bitrev16(u16 in) { TRACE; return 0; }
************************/
void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index) { TRACE; return 0; }
int radix_tree_insert(struct radix_tree_root *root, unsigned long index, void *item) { TRACE; return 0; }
void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) { TRACE; return 0; }
void radix_tree_preload_end(void) { TRACE; }
int radix_tree_insert(struct radix_tree_root *root, unsigned long index, void *item) { TRACE; return 0; }
int radix_tree_maybe_preload(gfp_t gfp_mask) { TRACE; return 0; }
/******************
** linux/gpio.h **
@ -1036,6 +1075,14 @@ int devm_gpio_request_one(struct device *dev, unsigned gpio,
const char *propname, int index) { TRACE; return 0; }
/********************
** linux/module.h **
********************/
void module_put(struct module *m) { TRACE; }
void __module_get(struct module *m) { TRACE; }
/******************
** linux/phy.h **
******************/
@ -1054,6 +1101,13 @@ int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd) { TRAC
int phy_start_aneg(struct phy_device *phydev) { TRACE; return 0; }
void phy_start(struct phy_device *phydev) { TRACE; }
void phy_stop(struct phy_device *phydev) { TRACE; }
int phy_init(struct phy *phy) { TRACE; return 0; }
int phy_exit(struct phy *phy) { TRACE; return 0; }
int phy_power_on(struct phy *phy) { TRACE; return 0; }
int phy_power_off(struct phy *phy) { TRACE; return 0; }
int phy_create_lookup(struct phy *phy, const char *con_id, const char *dev_id) { TRACE; return 0; }
void phy_remove_lookup(struct phy *phy, const char *con_id, const char *dev_id) { TRACE; }
int genphy_resume(struct phy_device *phydev) { TRACE; return 0; }
struct phy_device * phy_connect(struct net_device *dev, const char *bus_id,
@ -1068,6 +1122,8 @@ struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index) { TRACE; retu
struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index) { TRACE; return 0; }
void usb_put_phy(struct usb_phy *x) { TRACE; }
struct phy *devm_phy_get(struct device *dev, const char *string) { TRACE; return 0; }
/****************
** linux/of.h **
@ -1082,6 +1138,18 @@ int of_platform_populate(struct device_node *root, const struct of_device_i
int of_device_is_compatible(const struct device_node *device, const char *compat) { TRACE; return 1; }
/**********************
** linux/property.h **
**********************/
bool device_property_read_bool(struct device *dev, const char *propname) { TRACE; return false; }
int device_property_read_u8(struct device *dev, const char *propname, u8 *val) { TRACE; return 0; }
int device_property_read_string(struct device *dev, const char *propname,
const char **val) { TRACE; *val = 0; return -EINVAL; }
int device_property_read_u32(struct device *dev, const char *propname, u32 *val) { TRACE; return 0; }
/******************************
** drivers/usb/dwc3/debug.h **
******************************/
@ -1090,11 +1158,26 @@ struct dwc3;
int dwc3_debugfs_init(struct dwc3 *d){ SKIP; return 0; }
void dwc3_debugfs_exit(struct dwc3 *d) { SKIP; }
void dwc3_trace(void (*trace)(struct va_format *), const char *fmt, ...) { SKIP; }
/**************************
** linux/power_supply.h **
**************************/
#include <linux/power_supply.h>
int power_supply_register(struct device *parent, struct power_supply *psy) { TRACE; return 0; }
struct power_supply *
power_supply_register(struct device *parent, const struct power_supply_desc *desc,
const struct power_supply_config *cfg) { TRACE; return 0; }
void power_supply_unregister(struct power_supply *psy) { TRACE; }
int power_supply_powers(struct power_supply *psy, struct device *dev) { TRACE; return 0; }
void *power_supply_get_drvdata(struct power_supply *psy) { TRACE; return 0; }
void power_supply_changed(struct power_supply *psy) { TRACE; }
/*********************
** linux/kobject.h **
*********************/
void kobject_put(struct kobject *kobj) { TRACE; }
struct kobject *kobject_create_and_add(const char *name, struct kobject *kobj) { TRACE; return 0; }

View File

@ -1,26 +0,0 @@
/*
* \brief Include before including Linux headers in C++
* \author Christian Helmuth
* \date 2014-08-21
*/
/*
* Copyright (C) 2014 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#define extern_c_begin
extern "C" {
/* some warnings should only be switched of for Linux headers */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpointer-arith"
#pragma GCC diagnostic ignored "-Wsign-compare"
/* deal with C++ keywords used for identifiers etc. */
#define private private_
#define class class_
#define new new_

View File

@ -1,20 +0,0 @@
/*
* \brief Include after including Linux headers in C++
* \author Christian Helmuth
* \date 2014-08-21
*/
/*
* Copyright (C) 2014 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#undef new
#undef class
#undef private
#pragma GCC diagnostic pop
} /* extern "C" */

View File

@ -1,102 +0,0 @@
/*
* \brief Slightly improved list
* \author Christian Helmuth
* \date 2014-09-25
*/
/*
* Copyright (C) 2014 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _LIST_H_
#define _LIST_H_
#include <util/list.h>
namespace Lx {
template <typename> class List;
template <typename> class List_element;
}
template <typename LT>
class Lx::List : private Genode::List<LT>
{
private:
typedef Genode::List<LT> Base;
public:
using Base::Element;
void append(LT const *le)
{
LT *at = nullptr;
for (LT *l = first(); l; l = l->next())
at = l;
Base::insert(le, at);
}
void prepend(LT const *le)
{
Base::insert(le);
}
void insert_before(LT const *le, LT const *at)
{
if (at == first()) {
prepend(le);
return;
} else if (!at) {
append(le);
return;
}
for (LT *l = first(); l; l = l->next())
if (l->next() == at)
at = l;
Base::insert(le, at);
}
/****************************
** Genode::List interface **
****************************/
LT *first() { return Base::first(); }
LT const *first() const { return Base::first(); }
void insert(LT const *le, LT const *at = 0)
{
Base::insert(le, at);
}
void remove(LT const *le)
{
Base::remove(le);
}
};
template <typename T>
class Lx::List_element : public Lx::List<List_element<T> >::Element
{
private:
T *_object;
public:
List_element(T *object) : _object(object) { }
T *object() const { return _object; }
};
#endif /* _LIST_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,214 +0,0 @@
/*
* \brief Pseudo-thread implementation using setjmp/longjmp
* \author Sebastian Sumpf <Sebastian.Sumpf@genode-labs.com>
* \date 2012-04-25
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _ROUTINE_H_
#define _ROUTINE_H_
#include <base/env.h>
#include <util/list.h>
#include <setjmp.h>
#include <platform/platform.h>
static const bool verbose = false;
namespace Timer {
void update_jiffies();
}
/**
* Allows pseudo-parallel execution of functions
*/
class Routine : public Genode::List<Routine>::Element
{
private:
enum { STACK_SIZE = 4 * 1024 * sizeof(long) };
bool _started; /* true if already started */
jmp_buf _env; /* state */
int (*_func)(void *); /* function to call*/
void *_arg; /* argument for function */
char const *_name; /* name of this object */
char *_stack; /* stack pointer */
static Routine *_current; /* currently scheduled object */
static Routine *_dead; /* object to remove */
static Routine *_main; /* main routine */
static bool _all; /* true when all objects must be scheduled */
/**
* List containing all registered objects
*/
static Genode::List<Routine> *_list()
{
static Genode::List<Routine> _l;
return &_l;
}
/**
* Start/restore
*/
void _run()
{
/* will never return */
if (!_started) {
_started = true;
Genode::Thread *th = Genode::Thread::myself();
_stack = (char *) th->alloc_secondary_stack(_name, STACK_SIZE);
if (verbose)
PDBG("Start func %s (%p) sp: %p", _name, _func, _stack);
/* XXX move to platform code */
/* switch stack and call '_func(_arg)' */
platform_execute((void *)(_stack), (void *)_func, _arg);
}
/* restore old state */
if (verbose)
PDBG("Schedule %s (%p)", _name, _func);
_longjmp(_env, 1);
}
/**
* Check for and remove dead objects
*/
static void _check_dead()
{
if (!_dead)
return;
_list()->remove(_dead);
destroy(Genode::env()->heap(), _dead);
_dead = 0;
}
/**
* Get next object to schedule
*/
static Routine *_next(bool all)
{
/* on schedule all start at first element */
if (all) {
_all = true;
return _list()->first();
}
/* disable all at last element */
if (_all && _current && !_current->next())
_all = false;
/* return next element (wrap at the end) */
return _current && _current->next() ? _current->next() : _list()->first();
}
public:
Routine(int (*func)(void*), void *arg, char const *name, bool started)
: _started(started), _func(func), _arg(arg), _name(name), _stack(0) { }
~Routine()
{
if (_stack)
Genode::Thread::myself()->free_secondary_stack(_stack);
}
/**
* Schedule next object
*
* If all is true, each object will be scheduled once.
*/
static void schedule(bool all = false, bool main = false)
__attribute__((noinline))
{
if (!_list()->first() && !_main)
return;
if (_current == _main)
all = true;
Routine *next = main ? _main : _next(all);
if (next == _current) {
_check_dead();
return;
}
/* return when restored */
if (_current && _setjmp(_current->_env)) {
_check_dead();
return;
}
_current = next;
_current->_run();
}
/**
* Schedule each object once
*/
static void schedule_all() { schedule(true); }
/**
* Set current to first object
*/
static void make_main_current() { _main = _current = _list()->first(); }
/**
* Add an object
*/
static Routine *add(int (*func)(void *), void *arg, char const *name,
bool started = false)
{
Routine *r = new (Genode::env()->heap()) Routine(func, arg, name, started);
_list()->insert(r);
return r;
}
/**
* Remove this object
*/
static void remove(Routine *r = nullptr)
{
if (!_current && !r)
return;
_dead = r ? r : _current;
schedule_main();
}
static void main()
{
if (!_current)
return;
_list()->remove(_current);
if (_main && _setjmp(_main->_env))
return;
schedule();
}
static void schedule_main() { schedule(false, true); }
/**
* True when 'schedule_all' has been called and is still in progress
*/
static bool all() { return _all; }
};
#endif /* _ROUTINE_H_ */

View File

@ -19,41 +19,7 @@
#include <base/signal.h>
#include <os/server.h>
#include "routine.h"
/**
* This singleton currently received all signals
*/
class Service_handler
{
private:
Service_handler() { }
public:
static Service_handler * s()
{
static Service_handler _s;
return &_s;
}
/**
* Dispatch for wait for signal
*/
void process()
{
Timer::update_jiffies();
if (Routine::all()) {
Routine::schedule();
return;
}
Routine::schedule_main();
}
};
static bool const verbose = false;
/**
* Helper that holds sender and entrypoint
@ -74,21 +40,6 @@ class Signal_helper
};
namespace Timer
{
void init(Server::Entrypoint &ep);
}
namespace Irq
{
void init(Server::Entrypoint &ep);
void check_irq();
}
namespace Event
{
void init(Server::Entrypoint &ep);
}
namespace Storage
{

View File

@ -131,6 +131,8 @@ int regulator_disable(struct regulator *);
void regulator_put(struct regulator *regulator);
struct regulator *regulator_get(struct device *dev, const char *id);
struct regulator *__must_check devm_regulator_get(struct device *dev,
const char *id);
/*******************************************
** arch/arm/plat-omap/include/plat/usb.h **
@ -174,11 +176,16 @@ int devm_gpio_request_one(struct device *dev, unsigned gpio,
****************/
#define of_match_ptr(ptr) NULL
#define for_each_available_child_of_node(parent, child) while (0)
unsigned of_usb_get_maximum_speed(struct device_node *np);
unsigned of_usb_get_dr_mode(struct device_node *np);
int of_device_is_compatible(const struct device_node *device,
const char *);
int of_device_is_compatible(const struct device_node *device, const char *);
void of_node_put(struct device_node *node);
int of_property_read_u32(const struct device_node *np, const char *propname,
u32 *out_value);
/*************************
@ -240,6 +247,10 @@ int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd);
void phy_start(struct phy_device *phydev);
int phy_start_aneg(struct phy_device *phydev);
void phy_stop(struct phy_device *phydev);
int phy_create_lookup(struct phy *phy, const char *con_id, const char *dev_id);
void phy_remove_lookup(struct phy *phy, const char *con_id, const char *dev_id);
int genphy_resume(struct phy_device *phydev);
struct phy_device * phy_connect(struct net_device *dev, const char *bus_id,
@ -247,6 +258,25 @@ struct phy_device * phy_connect(struct net_device *dev, const char *bus_id,
phy_interface_t interface);
void phy_disconnect(struct phy_device *phydev);
struct phy *devm_phy_get(struct device *dev, const char *string);
struct phy *devm_of_phy_get(struct device *dev, struct device_node *np,
const char *con_id);
/*********************************
** linux/usb/usb_phy_generic.h **
*********************************/
#include <linux/usb/ch9.h>
#include <linux/usb/phy.h>
struct usb_phy_generic_platform_data
{
enum usb_phy_type type;
int gpio_reset;
};
/*******************************
** linux/usb/nop-usb-xceiv.h **
@ -276,7 +306,7 @@ void *dma_to_virt(struct device *dev, dma_addr_t addr);
void local_fiq_disable();
void local_fiq_enable();
unsigned smp_processor_id(void);
/***************
** asm/fiq.h **
@ -300,7 +330,20 @@ struct usb_phy_gen_xceiv_platform_data
int gpio_reset;
};
#include <linux/usb/ch9.h>
#include <linux/usb/phy.h>
/******************************
** linux/usb/xhci_pdriver.h **
******************************/
struct usb_xhci_pdata {
unsigned usb3_lpm_capable:1;
};
/******************
** asm/memory.h **
******************/
#define __bus_to_virt phys_to_virt
#endif /* _ARM__PLATFORM__LX_EMUL_H_ */

View File

@ -1,33 +0,0 @@
/*
* \brief Platform specific part of memory allocation
* \author Alexander Boettcher
* \date 2013-03-18
*/
/*
* Copyright (C) 2013-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _ARM__PLATFORM__LX_MEM_
#define _ARM__PLATFORM__LX_MEM_
#include <base/cache.h>
class Backend_memory {
public:
static Genode::Ram_dataspace_capability alloc(Genode::addr_t size,
Genode::Cache_attribute c)
{
return Genode::env()->ram_session()->alloc(size, c);
}
static void free(Genode::Ram_dataspace_capability cap) {
return Genode::env()->ram_session()->free(cap); }
};
#endif /* _ARM__PLATFORM__LX_MEM_ */

View File

@ -1,35 +0,0 @@
/**
* \brief Platform specific code
* \author Sebastian Sumpf
* \date 2012-06-10
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _ARM__PLATFORM_H_
#define _ARM__PLATFORM_H_
#ifdef __cplusplus
extern "C" {
#endif
static inline
void platform_execute(void *sp, void *func, void *arg)
{
asm volatile ("mov r0, %2;" /* set arg */
"mov sp, %0;" /* set stack */
"mov pc, %1;" /* call func */
""
: : "r"(sp), "r"(func), "r"(arg) : "r0");
}
#ifdef __cplusplus
}
#endif
#endif /* _ARM__PLATFORM_H_ */

View File

@ -0,0 +1,73 @@
/**
* \brief Platform_device implementation for ARM
* \author Sebastian Sumpf
* \date 2016-04-25
*
* Note: Throw away when there exists a plaform device implementation for ARM
* in generic code
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_
#define _ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_
#include <platform_device/device.h>
#include <irq_session/connection.h>
#include <util/list.h>
#include <util/volatile_object.h>
namespace Platform { struct Device; }
struct Platform::Device : Platform::Abstract_device, Genode::List<Device>::Element
{
unsigned irq_num;
Genode::Lazy_volatile_object<Genode::Irq_connection> irq_connection;
Device(unsigned irq) : irq_num(irq) { }
unsigned vendor_id() { return ~0U; }
unsigned device_id() { return ~0U; }
Genode::Irq_session_capability irq(Genode::uint8_t) override
{
irq_connection.construct(irq_num);
return irq_connection->cap();
}
Genode::Io_mem_session_capability io_mem(Genode::uint8_t,
Genode::Cache_attribute,
Genode::addr_t, Genode::size_t) override
{
PERR("%s: not implemented", __PRETTY_FUNCTION__);
return Genode::Io_mem_session_capability();
}
static Genode::List<Device> &list()
{
static Genode::List<Device> l;
return l;
}
static Device &create(unsigned irq_num)
{
Device *d;
for (d = list().first(); d; d = d->next())
if (d->irq_num == irq_num)
return *d;
d = new (Genode::env()->heap()) Device(irq_num);
list().insert(d);
return *d;
}
};
#endif /* _ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_ */

View File

@ -18,15 +18,6 @@
** asm/barrier.h **
*******************/
#define mb() asm volatile ("": : :"memory")
#define rmb() mb()
#define wmb() asm volatile ("": : :"memory")
#define smp_mb() asm volatile ("": : :"memory")
#define smp_rmb() smp_mb()
#define smp_wmb() asm volatile ("": : :"memory")
static inline void barrier() { asm volatile ("": : :"memory"); }
#include <lx_emul/barrier.h>
#endif /* _ARMV6__PLATFORM__LX_EMUL_BARRIER_H_ */

View File

@ -18,20 +18,6 @@
** asm/barrier.h **
*******************/
/*
* This is the "safe" implementation as needed for a configuration
* with bufferable DMA memory and SMP enabled.
*/
#define mb() asm volatile ("dsb": : :"memory")
#define rmb() mb()
#define wmb() asm volatile ("dsb st": : :"memory")
#define smp_mb() asm volatile ("dmb ish": : :"memory")
#define smp_rmb() smp_mb()
#define smp_wmb() asm volatile ("dmb ishst": : :"memory")
static inline void barrier() { asm volatile ("": : :"memory"); }
#include <lx_emul/barrier.h>
#endif /* _ARMV7__PLATFORM__LX_EMUL_BARRIER_H_ */

View File

@ -14,28 +14,20 @@
#ifndef _X86_32__PLATFORM__LX_EMUL_
#define _X86_32__PLATFORM__LX_EMUL_
struct platform_device
{
void *data;
};
/*******************
** asm/barrier.h **
*******************/
#define mb() asm volatile ("mfence": : :"memory")
#define rmb() asm volatile ("lfence": : :"memory")
#define wmb() asm volatile ("sfence": : :"memory")
#include <lx_emul/barrier.h>
/*
* This is the "safe" implementation as needed for a configuration
* with SMP enabled.
*/
#define smp_mb() mb()
#define smp_rmb() barrier()
#define smp_wmb() barrier()
struct platform_device
{
void *data;
};
static inline void barrier() { asm volatile ("": : :"memory"); }
#define dev_is_pci(d) (1)
#endif /* _X86_32__PLATFORM__LX_EMUL_ */

View File

@ -1,29 +0,0 @@
/*
* \brief Platform specific part of memory allocation
* \author Alexander Boettcher
* \date 2013-03-18
*/
/*
* Copyright (C) 2013-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _X86__PLATFORM__LX_MEM_
#define _X86__PLATFORM__LX_MEM_
#include <base/cache.h>
class Backend_memory {
public:
static Genode::Ram_dataspace_capability alloc(Genode::addr_t size,
Genode::Cache_attribute);
static void free(Genode::Ram_dataspace_capability cap);
};
#endif /* _X86__PLATFORM__LX_MEM_ */

View File

@ -1,29 +0,0 @@
/**
* \brief Platform specific code
* \author Sebastian Sumpf
* \date 2012-06-10
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _X86_32__PLATFORM_H_
#define _X86_32__PLATFORM_H_
#include <platform.h>
static inline
void platform_execute(void *sp, void *func, void *arg)
{
asm volatile ("movl %2, 0(%0);"
"movl %1, -0x4(%0);"
"movl %0, %%esp;"
"call *-4(%%esp);"
: : "r" (sp), "r" (func), "r" (arg));
}
#endif /* _X86_32__PLATFORM_H_ */

View File

@ -1,34 +0,0 @@
/**
* \brief Platform specific code
* \author Sebastian Sumpf
* \author Alexander Boettcher
* \date 2012-06-10
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _X86_64__PLATFORM_H_
#define _X86_64__PLATFORM_H_
#include <platform.h>
static inline
void platform_execute(void *sp, void *func, void *arg)
{
asm volatile ("movq %0, %%rsp;" /* load stack pointer */
"movq %%rsp, %%rbp;" /* caller stack frame (for GDB debugging) */
"movq %0, -8(%%rbp);"
"movq %1, -16(%%rbp);"
"movq %2, -24(%%rbp);"
"sub $24, %%rsp;" /* adjust to next stack frame */
"movq %2, %%rdi;" /* 1st argument */
"call *-16(%%rbp);" /* call func */
: : "r" (sp), "r" (func), "r" (arg));
}
#endif /* _X86_64__PLATFORM_H_ */

View File

@ -18,11 +18,9 @@
#include <input/root.h>
#include <os/ring_buffer.h>
#include <extern_c_begin.h>
#include <lx_emul.h>
#include <extern_c_end.h>
#include "platform.h"
#undef RELEASE
using namespace Genode;

View File

@ -20,362 +20,25 @@
#include <util/string.h>
/* Local includes */
#include "routine.h"
#include "signal.h"
#include "platform/lx_mem.h"
#include <extern_c_begin.h>
#include "lx_emul.h"
#include <extern_c_end.h>
#include <lx_kit/backend_alloc.h>
#include <lx_kit/irq.h>
#include <lx_kit/scheduler.h>
#include <lx_kit/work.h>
#include <lx_emul/impl/slab.h>
namespace Genode {
class Slab_backend_alloc;
class Slab_alloc;
}
/**
* Back-end allocator for Genode's slab allocator
*/
class Genode::Slab_backend_alloc : public Genode::Allocator,
public Genode::Rm_connection,
public Genode::Region_map_client
{
private:
enum {
VM_SIZE = 64 * 1024 * 1024, /* size of VM region to reserve */
P_BLOCK_SIZE = 2 * 1024 * 1024, /* 2 MB physical contiguous */
V_BLOCK_SIZE = P_BLOCK_SIZE * 2, /* 2 MB virtual used, 2 MB virtual left free to avoid that Allocator_avl merges virtual contiguous regions which are physically non-contiguous */
ELEMENTS = VM_SIZE / V_BLOCK_SIZE /* MAX number of dataspaces in VM */
};
addr_t _base; /* virt. base address */
Genode::Cache_attribute _cached; /* non-/cached RAM */
Ram_dataspace_capability _ds_cap[ELEMENTS]; /* dataspaces to put in VM */
addr_t _ds_phys[ELEMENTS]; /* physical bases of dataspaces */
int _index; /* current index in ds_cap */
Allocator_avl _range; /* manage allocations */
bool _alloc_block()
{
if (_index == ELEMENTS) {
PERR("Slab-backend exhausted!");
return false;
}
try {
_ds_cap[_index] = Backend_memory::alloc(P_BLOCK_SIZE, _cached);
/* attach at index * V_BLOCK_SIZE */
Region_map_client::attach_at(_ds_cap[_index], _index * V_BLOCK_SIZE, P_BLOCK_SIZE, 0);
/* lookup phys. address */
_ds_phys[_index] = Dataspace_client(_ds_cap[_index]).phys_addr();
} catch (...) { return false; }
/* return base + offset in VM area */
addr_t block_base = _base + (_index * V_BLOCK_SIZE);
++_index;
_range.add_range(block_base, P_BLOCK_SIZE);
return true;
}
public:
Slab_backend_alloc(Genode::Cache_attribute cached)
:
Region_map_client(Rm_connection::create(VM_SIZE)),
_cached(cached), _index(0), _range(env()->heap())
{
/* reserver attach us, anywere */
_base = env()->rm_session()->attach(dataspace());
}
/**
* Allocate
*/
bool alloc(size_t size, void **out_addr) override
{
bool done = _range.alloc(size, out_addr);
if (done)
return done;
done = _alloc_block();
if (!done) {
PERR("Backend allocator exhausted\n");
return false;
}
return _range.alloc(size, out_addr);
}
void free(void *addr) { _range.free(addr); }
void free(void *addr, size_t size) override { _range.free(addr, size); }
size_t overhead(size_t size) const override { return 0; }
bool need_size_for_free() const override { return false; }
/**
* Return phys address for given virtual addr.
*/
addr_t phys_addr(addr_t addr)
{
if (addr < _base || addr >= (_base + VM_SIZE))
return ~0UL;
int index = (addr - _base) / V_BLOCK_SIZE;
/* physical base of dataspace */
addr_t phys = _ds_phys[index];
if (!phys)
return ~0UL;
/* add offset */
phys += (addr - _base - (index * V_BLOCK_SIZE));
return phys;
}
/**
* Translate given physical address to virtual address
*
* \return virtual address, or 0 if no translation exists
*/
addr_t virt_addr(addr_t phys)
{
for (unsigned i = 0; i < ELEMENTS; i++) {
if (_ds_cap[i].valid()
&& phys >= _ds_phys[i] && phys < _ds_phys[i] + P_BLOCK_SIZE)
return _base + i * V_BLOCK_SIZE + (phys - _ds_phys[i]);
}
PWRN("virt_addr(0x%lx) - no translation", phys);
return 0;
}
addr_t start() const { return _base; }
addr_t end() const { return _base + VM_SIZE - 1; }
};
/**
* Slab allocator using our back-end allocator
*/
class Genode::Slab_alloc : public Genode::Slab
{
private:
Genode::size_t const _object_size;
static Genode::size_t _calculate_block_size(Genode::size_t object_size)
{
Genode::size_t const block_size = 16*object_size;
return Genode::align_addr(block_size, 12);
}
public:
Slab_alloc(Genode::size_t object_size, Slab_backend_alloc &allocator)
:
Slab(object_size, _calculate_block_size(object_size), 0, &allocator),
_object_size(object_size)
{ }
Genode::addr_t alloc()
{
Genode::addr_t result;
return (Slab::alloc(_object_size, (void **)&result) ? result : 0);
}
void free(void *ptr) { Slab::free(ptr, _object_size); }
};
/**
* Memory interface used used for Linux emulation
*/
class Malloc
{
private:
enum {
SLAB_START_LOG2 = 3, /* 8 B */
SLAB_STOP_LOG2 = 16, /* 64 KB */
NUM_SLABS = (SLAB_STOP_LOG2 - SLAB_START_LOG2) + 1,
};
typedef Genode::addr_t addr_t;
typedef Genode::Slab_alloc Slab_alloc;
typedef Genode::Slab_backend_alloc Slab_backend_alloc;
Slab_backend_alloc *_back_allocator;
Slab_alloc *_allocator[NUM_SLABS];
Genode::Cache_attribute _cached; /* cached or un-cached memory */
addr_t _start; /* VM region of this allocator */
addr_t _end;
/**
* Set 'value' at 'addr'
*/
void _set_at(addr_t addr, addr_t value) { *((addr_t *)addr) = value; }
/**
* Retrieve slab index belonging to given address
*/
unsigned _slab_index(Genode::addr_t **addr)
{
using namespace Genode;
/* get index */
addr_t index = *(*addr - 1);
/*
* If index large, we use aligned memory, retrieve beginning of slab entry
* and read index from there
*/
if (index > 32) {
*addr = (addr_t *)*(*addr - 1);
index = *(*addr - 1);
}
return index;
}
public:
Malloc(Slab_backend_alloc *alloc, Genode::Cache_attribute cached)
: _back_allocator(alloc), _cached(cached), _start(alloc->start()),
_end(alloc->end())
{
/* init slab allocators */
for (unsigned i = SLAB_START_LOG2; i <= SLAB_STOP_LOG2; i++)
_allocator[i - SLAB_START_LOG2] = new (Genode::env()->heap())
Slab_alloc(1U << i, *alloc);
}
static unsigned long max_alloc() { return 1U << SLAB_STOP_LOG2; }
/**
* Alloc in slabs
*/
void *alloc(Genode::size_t size, int align = 0, Genode::addr_t *phys = 0)
{
using namespace Genode;
/* += slab index + aligment size */
size += sizeof(addr_t) + (align > 2 ? (1 << align) : 0);
int msb = Genode::log2(size);
if (size > (1U << msb))
msb++;
if (size < (1U << SLAB_START_LOG2))
msb = SLAB_STOP_LOG2;
if (msb > SLAB_STOP_LOG2) {
PERR("Slab too large %u reqested %zu cached %d", 1U << msb, size, _cached);
return 0;
}
addr_t addr = _allocator[msb - SLAB_START_LOG2]->alloc();
if (!addr) {
PERR("Failed to get slab for %u", 1 << msb);
return 0;
}
_set_at(addr, msb - SLAB_START_LOG2);
addr += sizeof(addr_t);
if (align > 2) {
/* save */
addr_t ptr = addr;
addr_t align_val = (1U << align);
addr_t align_mask = align_val - 1;
/* align */
addr = (addr + align_val) & ~align_mask;
/* write start address before aligned address */
_set_at(addr - sizeof(addr_t), ptr);
}
if (phys)
*phys = _back_allocator->phys_addr(addr);
return (addr_t *)addr;
}
void free(void const *a)
{
using namespace Genode;
addr_t *addr = (addr_t *)a;
unsigned nr = _slab_index(&addr);
_allocator[nr]->free((void *)(addr - 1));
}
void *alloc_large(size_t size)
{
void *addr;
if (!_back_allocator->alloc(size, &addr)) {
PERR("Large back end allocation failed (%zu bytes)", size);
return nullptr;
}
return addr;
}
void free_large(void *ptr)
{
_back_allocator->free(ptr);
}
Genode::addr_t phys_addr(void *a)
{
return _back_allocator->phys_addr((addr_t)a);
}
Genode::addr_t virt_addr(Genode::addr_t phys)
{
return _back_allocator->virt_addr(phys);
}
/**
* Belongs given address to this allocator
*/
bool inside(addr_t const addr) const { return (addr > _start) && (addr <= _end); }
/**
* Cached memory allocator
*/
static Malloc *mem()
{
static Slab_backend_alloc _b(Genode::CACHED);
static Malloc _m(&_b, Genode::CACHED);
return &_m;
}
/**
* DMA allocator
*/
static Malloc *dma()
{
static Slab_backend_alloc _b(Genode::UNCACHED);
static Malloc _m(&_b, Genode::UNCACHED);
return &_m;
}
};
void lx_printf(char const *fmt, ...)
{
va_list va;
va_start(va, fmt);
Genode::vprintf(fmt, va);
va_end(va);
}
void lx_vprintf(char const *fmt, va_list va) {
Genode::vprintf(fmt, va); }
unsigned long jiffies;
void backtrace() { }
/***********************
@ -386,15 +49,15 @@ void lx_vprintf(char const *fmt, va_list va) {
* Actually not atomic, for now
*/
unsigned int atomic_read(atomic_t *p) { return *(volatile int *)p; }
unsigned int atomic_read(atomic_t *p) { return p->v; }
void atomic_inc(atomic_t *v) { (*(volatile int *)v)++; }
void atomic_dec(atomic_t *v) { (*(volatile int *)v)--; }
void atomic_inc(atomic_t *v) { v->v++; }
void atomic_dec(atomic_t *v) { v->v--; }
void atomic_add(int i, atomic_t *v) { (*(volatile int *)v) += i; }
void atomic_sub(int i, atomic_t *v) { (*(volatile int *)v) -= i; }
void atomic_add(int i, atomic_t *v) { v->v += i; }
void atomic_sub(int i, atomic_t *v) { v->v -= i; }
void atomic_set(atomic_t *p, unsigned int v) { (*(volatile int *)p) = v; }
void atomic_set(atomic_t *p, unsigned int v) { p->v = v; }
/*************************************
@ -403,58 +66,13 @@ void atomic_set(atomic_t *p, unsigned int v) { (*(volatile int *)p) = v; }
void *dma_malloc(size_t size)
{
return Malloc::dma()->alloc_large(size);
return Lx::Malloc::dma().alloc_large(size);
}
void dma_free(void *ptr)
{
Malloc::dma()->free_large(ptr);
}
void *kmalloc(size_t size, gfp_t flags)
{
void *addr = flags & GFP_NOIO ? Malloc::dma()->alloc(size) : Malloc::mem()->alloc(size);
unsigned long a = (unsigned long)addr;
if (a & 0x3)
PERR("Unaligned kmalloc %lx", a);
//PDBG("Kmalloc: [%lx-%lx) from %p", a, a + size, __builtin_return_address(0));
return addr;
}
void *kzalloc(size_t size, gfp_t flags)
{
void *addr = kmalloc(size, flags);
if (addr)
Genode::memset(addr, 0, size);
return addr;
}
void *kcalloc(size_t n, size_t size, gfp_t flags)
{
if (size != 0 && n > ~0UL / size)
return 0;
return kzalloc(n * size, flags);
}
void kfree(const void *p)
{
if (!p)
return;
if (Malloc::mem()->inside((Genode::addr_t)p))
Malloc::mem()->free(p);
if (Malloc::dma()->inside((Genode::addr_t)p))
Malloc::dma()->free(p);
Lx::Malloc::dma().free_large(ptr);
}
@ -588,7 +206,11 @@ int scnprintf(char *buf, size_t size, const char *fmt, ...)
return sc.len();
}
int strcmp(const char *s1, const char *s2) { return Genode::strcmp(s1, s2); }
int strcmp(const char *s1, const char *s2)
{
printk("%s:%d from %p\n", __func__, __LINE__, __builtin_return_address(0));
return Genode::strcmp(s1, s2);
}
size_t strlen(const char *s) { return Genode::strlen(s); }
@ -621,14 +243,6 @@ size_t strlcpy(char *dest, const char *src, size_t size)
}
void *kmemdup(const void *src, size_t len, gfp_t gfp)
{
void *ptr = kmalloc(len, gfp);
memcpy(ptr, src, len);
return ptr;
}
void *memscan(void *addr, int c, size_t size)
{
unsigned char* p = (unsigned char *)addr;
@ -652,75 +266,28 @@ int ilog2(u32 n) { return Genode::log2(n); }
** linux/slab.h **
********************/
struct kmem_cache
{
const char *name; /* cache name */
unsigned size; /* object size */
};
struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align,
unsigned long falgs, void (*ctor)(void *))
{
lx_log(DEBUG_SLAB, "\"%s\" obj_size=%zd", name, size);
if (size > Malloc::max_alloc()) {
PERR("kmem_cache_create: slab size > %lu", Malloc::max_alloc());
return 0;
}
struct kmem_cache *cache;
if (!name) {
printk("kmem_cache name reqeuired\n");
return 0;
}
cache = (struct kmem_cache *)kmalloc(sizeof(*cache), 0);
if (!cache) {
printk("No memory for slab cache\n");
return 0;
}
cache->name = name;
cache->size = size;
return cache;
}
void kmem_cache_destroy(struct kmem_cache *cache)
{
lx_log(DEBUG_SLAB, "\"%s\"", cache->name);
kfree(cache);
destroy(Genode::env()->heap(), cache);
}
void *kmem_cache_zalloc(struct kmem_cache *cache, gfp_t flags)
{
void *ret;
lx_log(DEBUG_SLAB, "\"%s\" flags=%x", cache->name, flags);
ret = kzalloc(cache->size, flags);
ret = kmem_cache_alloc(cache, flags);
memset(ret, 0, cache->size());
return ret;
}
void kmem_cache_free(struct kmem_cache *cache, void *objp)
{
lx_log(DEBUG_SLAB, "\"%s\" (%p)", cache->name, objp);
kfree(objp);
}
/**********************
** asm-generic/io.h **
**********************/
void *phys_to_virt(unsigned long address)
{
return (void *)Malloc::dma()->virt_addr(address);
return (void *)Lx::Malloc::dma().virt_addr(address);
}
@ -847,6 +414,22 @@ int dev_set_drvdata(struct device *dev, void *data)
const char *dev_name(const struct device *dev) { return dev->name; }
/*******************************
** asm-generic/bitops/find.h **
*******************************/
unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
unsigned long offset)
{
unsigned long i = offset / BITS_PER_LONG;
offset -= (i * BITS_PER_LONG);
for (; offset < size; offset++)
if (addr[i] & (1UL << offset))
return offset;
return size;
}
long find_next_zero_bit_le(const void *addr,
unsigned long size, unsigned long offset)
@ -944,30 +527,7 @@ int fls(int x)
** linux/delay.h **
*******************/
static Timer::Connection _timer;
void udelay(unsigned long usecs)
{
_timer.usleep(usecs);
}
void msleep(unsigned int msecs) { _timer.msleep(msecs); }
void mdelay(unsigned long msecs) { msleep(msecs); }
/*********************
** linux/jiffies.h **
*********************/
enum { JIFFIES_TICK_MS = 1000 / HZ };
unsigned long msecs_to_jiffies(const unsigned int m) { return m / JIFFIES_TICK_MS; }
unsigned int jiffies_to_msecs(const unsigned long j) { return j * JIFFIES_TICK_MS; }
long time_after_eq(long a, long b) { return (a - b) >= 0; }
long time_after(long a, long b) { return (b - a) < 0; }
#include <lx_emul/impl/delay.h>
/*********
@ -1016,13 +576,13 @@ void *dma_pool_alloc(struct dma_pool *d, gfp_t f, dma_addr_t *dma)
void dma_pool_free(struct dma_pool *d, void *vaddr, dma_addr_t a)
{
lx_log(DEBUG_DMA, "free: addr %p, size: %zx", vaddr, d->size);
Malloc::dma()->free(vaddr);
Lx::Malloc::dma().free(vaddr);
}
void *dma_alloc_coherent(struct device *, size_t size, dma_addr_t *dma, gfp_t)
{
void *addr = Malloc::dma()->alloc(size, PAGE_SHIFT, dma);
void *addr = Lx::Malloc::dma().alloc(size, PAGE_SHIFT, dma);
if (!addr)
return 0;
@ -1036,7 +596,7 @@ void *dma_alloc_coherent(struct device *, size_t size, dma_addr_t *dma, gfp_t)
void dma_free_coherent(struct device *, size_t size, void *vaddr, dma_addr_t)
{
lx_log(DEBUG_DMA, "free: addr %p, size: %zx", vaddr, size);
Malloc::dma()->free(vaddr);
Lx::Malloc::dma().free(vaddr);
}
@ -1049,7 +609,7 @@ dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr,
enum dma_data_direction dir,
struct dma_attrs *attrs)
{
dma_addr_t phys = (dma_addr_t)Malloc::dma()->phys_addr(ptr);
dma_addr_t phys = (dma_addr_t)Lx::Malloc::dma().phys_addr(ptr);
if (phys == ~0UL)
PERR("translation virt->phys %p->%lx failed, return ip %p", ptr, phys,
@ -1079,23 +639,16 @@ int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
*********************/
struct task_struct *kthread_run(int (*fn)(void *), void *arg, const char *n, ...)
{
lx_log(DEBUG_THREAD, "Run %s", n);
Routine::add(fn, arg, n);
return 0;
}
struct task_struct *kthread_create(int (*threadfn)(void *data),
void *data,
const char namefmt[], ...)
{
/*
* This is just called for delayed device scanning (see
* 'drivers/usb/storage/usb.c')
*/
lx_log(DEBUG_THREAD, "Create %s", namefmt);
Routine::add(threadfn, data, namefmt);
lx_log(DEBUG_THREAD, "Run %s", n);
new (Genode::env()->heap()) Lx::Task((void (*)(void *))fn, arg, n,
Lx::Task::PRIORITY_2,
Lx::scheduler());
return 0;
}
@ -1152,6 +705,15 @@ struct resource * devm_request_mem_region(struct device *dev, resource_size_t st
return r;
}
/*****************
** linux/smp.h **
*****************/
int smp_call_function_single(int cpu, smp_call_func_t func, void *info,
int wait) { func(info); return 0; }
/****************
** Networking **
****************/
@ -1275,44 +837,6 @@ int rounddown_pow_of_two(u32 n)
}
/******************
** linux/wait.h **
******************/
void init_waitqueue_head(wait_queue_head_t *q)
{
q->q = 0;
}
void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)
{
if (q->q) {
PERR("Non-empty wait queue");
return;
}
q->q = wait;
}
void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)
{
if (q->q != wait) {
PERR("Remove unkown element from wait queue");
return;
}
q->q = 0;
}
int waitqueue_active(wait_queue_head_t *q)
{
return q->q ? 1 : 0;
}
/*****************
** linux/nls.h **
*****************/
@ -1389,3 +913,116 @@ int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
{
return raw_notifier_call_chain((struct raw_notifier_head *)nh, val, v);
}
/*******************
** linux/timer.h **
*******************/
#include <lx_emul/impl/timer.h>
#include <lx_emul/impl/sched.h>
signed long schedule_timeout_uninterruptible(signed long timeout)
{
lx_log(DEBUG_COMPLETION, "%ld\n", timeout);
schedule_timeout(timeout);
return 0;
}
/************************
** linux/completion.h **
************************/
#include <lx_emul/impl/completion.h>
static void _completion_timeout(unsigned long t)
{
Lx::Task *task = (Lx::Task *)t;
task->unblock();
}
long __wait_completion(struct completion *work, unsigned long timeout)
{
timer_list t;
unsigned long j = timeout ? jiffies + timeout : 0;
if (timeout) {
setup_timer(&t, _completion_timeout, (unsigned long)Lx::scheduler().current());
mod_timer(&t, timeout);
}
while (!work->done) {
if (j && j <= jiffies) {
lx_log(1, "timeout jiffies %lu", jiffies);
return 0;
}
Lx::Task *task = Lx::scheduler().current();
work->task = (void *)task;
task->block_and_schedule();
}
if (timeout)
del_timer(&t);
work->done = 0;
return j ? j - jiffies : 1;
}
/***********************
** linux/workqueue.h **
***********************/
#include <lx_emul/impl/work.h>
void tasklet_init(struct tasklet_struct *t, void (*f)(unsigned long), unsigned long d)
{
t->func = f;
t->data = d;
}
void tasklet_schedule(struct tasklet_struct *tasklet)
{
Lx::Work *lx_work = (Lx::Work *)tasklet_wq->task;
lx_work->schedule_tasklet(tasklet);
lx_work->unblock();
}
void tasklet_hi_schedule(struct tasklet_struct *tasklet)
{
tasklet_schedule(tasklet);
}
struct workqueue_struct *create_singlethread_workqueue(char const *name)
{
workqueue_struct *wq = (workqueue_struct *)kzalloc(sizeof(workqueue_struct), 0);
Lx::Work *work = Lx::Work::alloc_work_queue(Genode::env()->heap(), name);
wq->task = (void *)work;
return wq;
}
struct workqueue_struct *alloc_workqueue(const char *fmt, unsigned int flags,
int max_active, ...)
{
return create_singlethread_workqueue(fmt);
}
/******************
** linux/wait.h **
******************/
#include <lx_emul/impl/wait.h>

View File

@ -23,8 +23,14 @@
/* Local */
#include <platform.h>
#include <routine.h>
#include <signal.h>
#include <lx_emul.h>
#include <lx_kit/irq.h>
#include <lx_kit/scheduler.h>
#include <lx_kit/timer.h>
#include <lx_kit/work.h>
using namespace Genode;
@ -43,16 +49,22 @@ extern "C" void module_raw_driver_init();
extern "C" void start_input_service(void *ep, void *services);
Routine *Routine::_current = 0;
Routine *Routine::_dead = 0;
Routine *Routine::_main = 0;
bool Routine::_all = false;
struct workqueue_struct *system_power_efficient_wq;
struct workqueue_struct *system_wq;
struct workqueue_struct *tasklet_wq;
void breakpoint() { PDBG("BREAK"); }
extern "C" int stdout_write(const char *);
static void init(Services *services)
static void run_linux(void *s)
{
Services *services = (Services *)s;
system_power_efficient_wq = alloc_workqueue("system_power_efficient_wq", 0, 0);
system_wq = alloc_workqueue("system_wq", 0, 0);
tasklet_wq = alloc_workqueue("tasklet_wq", 0, 0);
/*
* The RAW driver is initialized first to make sure that it doesn't miss
* notifications about added devices.
@ -79,34 +91,40 @@ static void init(Services *services)
module_wacom_driver_init();
}
/* host controller */
platform_hcd_init(services);
/* storage */
if (services->stor)
module_usb_storage_driver_init();
/* host controller */
platform_hcd_init(services);
while (true)
Lx::scheduler().current()->block_and_schedule();
}
void start_usb_driver(Server::Entrypoint &ep)
{
Services services;
static Services services;
if (services.hid)
start_input_service(&ep.rpc_ep(), &services);
Timer::init(ep);
Irq::init(ep);
Event::init(ep);
Storage::init(ep);
Nic::init(ep);
if (services.raw)
Raw::init(ep, services.raw_report_device_list);
Routine::add(0, 0, "Main", true);
Routine::make_main_current();
init(&services);
Lx::Scheduler &sched = Lx::scheduler();
Lx::Timer &timer = Lx::timer(&ep, &jiffies);
Routine::main();
Lx::Irq::irq(&ep, Genode::env()->heap());
Lx::Work::work_queue(Genode::env()->heap());
static Lx::Task linux(run_linux, &services, "linux", Lx::Task::PRIORITY_0,
Lx::scheduler());
Lx::scheduler().schedule();
}

View File

@ -19,11 +19,11 @@
#include <util/xml_node.h>
#include <os/config.h>
#include <extern_c_begin.h>
#include <lx_emul.h>
#include <lx_emul/extern_c_begin.h>
#include <linux/usb.h>
#include <linux/usb/usbnet.h>
#include <extern_c_end.h>
#include <lx_emul/extern_c_end.h>
#include <usb_nic_component.h>
#include "signal.h"

View File

@ -1,623 +0,0 @@
/*
* \brief Emulate 'pci_dev' structure
* \author Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
* \date 2012-04-02
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Genode base includes */
#include <base/object_pool.h>
#include <io_mem_session/client.h>
#include <irq_session/connection.h>
#include <ram_session/client.h>
#include <util/retry.h>
/* Genode os includes */
#include <io_port_session/client.h>
#include <platform_session/connection.h>
#include <platform_device/client.h>
#include <util/volatile_object.h>
/* Linux includes */
#include <extern_c_begin.h>
#include <lx_emul.h>
#include <extern_c_end.h>
#include <platform/lx_mem.h>
struct bus_type pci_bus_type;
using namespace Genode;
class Io_port
{
private:
unsigned _base = 0;
unsigned _size = 0;
Io_port_session_capability _cap;
Lazy_volatile_object<Io_port_session_client> _port;
bool _valid(unsigned port) {
return _cap.valid() && port >= _base && port < _base + _size; }
public:
~Io_port()
{
if (_cap.valid())
_port.destruct();
}
void session(unsigned base, unsigned size, Io_port_session_capability cap)
{
_base = base;
_size = size;
_cap = cap;
_port.construct(_cap);
}
template<typename POD>
bool out(unsigned port, POD val)
{
if (!_valid(port))
return false;
switch (sizeof(POD)) {
case 1: _port->outb(port, val); break;
case 2: _port->outw(port, val); break;
case 4: _port->outl(port, val); break;
}
return true;
}
template<typename POD>
bool in(unsigned port, POD *val)
{
if (!_valid(port))
return false;;
switch (sizeof(POD)) {
case 1: *val = _port->inb(port); break;
case 2: *val = _port->inw(port); break;
case 4: *val = _port->inl(port); break;
}
return true;
}
};
/**
* Virtual IRQ number (monotonically increasing)
*/
static unsigned virq_num()
{
static unsigned instance = 128;
return ++instance;
}
/**
* Scan PCI bus and probe for HCDs
*/
class Pci_driver : public Genode::List<Pci_driver>::Element
{
private:
pci_driver *_drv; /* Linux PCI driver */
Platform::Device_capability _cap; /* PCI cap */
pci_device_id const *_id; /* matched id for this driver */
Io_port _port;
public:
pci_dev *_dev; /* Linux PCI device */
private:
/* offset used in PCI config space */
enum Pci_config { IRQ = 0x3c, REV = 0x8, CMD = 0x4 };
/**
* Fill Linux device informations
*/
void _setup_pci_device()
{
using namespace Platform;
Device_client client(_cap);
uint8_t bus, dev, func;
client.bus_address(&bus, &dev, &func);
_dev = new (Genode::env()->heap()) pci_dev;
_dev->devfn = ((uint16_t)bus << 8) | (0xff & PCI_DEVFN(dev, func));
_dev->vendor = client.vendor_id();
_dev->device = client.device_id();
_dev->class_ = client.class_code();
_dev->revision = client.config_read(REV, Device::ACCESS_8BIT);
_dev->dev.driver = &_drv->driver;
/* dummy dma mask used to mark device as DMA capable */
static u64 dma_mask = ~(u64)0;
_dev->dev.dma_mask = &dma_mask;
_dev->dev.coherent_dma_mask = ~0;
/*
* We initialize the IRQ line with a virtual number to ensure that
* each device gets a unique number and, hence, requests its
* associated IRQ capability at the platform driver. Consequently,
* we give a away the questionable option to implement IRQ sharing
* locally and leave it to the platform driver, which just uses
* signalling anyway.
*/
_dev->irq = virq_num();
/* hide ourselfs in bus structure */
_dev->bus = (struct pci_bus *)this;
/* setup resources */
bool io = false;
for (unsigned i = 0; i < Device::NUM_RESOURCES; i++) {
Device::Resource res = client.resource(i);
_dev->resource[i].start = res.base();
_dev->resource[i].end = res.base() + res.size() - 1;
unsigned flags = 0;
if (res.type() == Device::Resource::IO) flags |= IORESOURCE_IO;
if (res.type() == Device::Resource::MEMORY) flags |= IORESOURCE_MEM;
_dev->resource[i].flags = flags;
/* request port I/O session */
if (res.type() == Device::Resource::IO) {
uint8_t virt_bar = client.phys_bar_to_virt(i);
_port.session(res.base(), res.size(), client.io_port(virt_bar));
io = true;
lx_log(DEBUG_PCI, "I/O [%u-%u)",
res.base(), res.base() + res.size());
}
/* request I/O memory (write combined) */
if (res.type() == Device::Resource::MEMORY)
lx_log(DEBUG_PCI, "I/O memory [%x-%x)", res.base(),
res.base() + res.size());
}
/* enable bus master and io bits */
uint16_t cmd = client.config_read(CMD, Device::ACCESS_16BIT);
cmd |= io ? 0x1 : 0;
/* enable bus master */
cmd |= 0x4;
client.config_write(CMD, cmd, Device::ACCESS_16BIT);
_drivers().insert(this);
}
/**
* Probe device with driver
*/
bool _probe()
{
_setup_pci_device();
if (!_drv->probe(_dev, _id))
return true;
PERR("Probe failed\n");
return false;
}
template <typename T>
Platform::Device::Access_size _access_size(T t)
{
switch (sizeof(T))
{
case 1:
return Platform::Device::ACCESS_8BIT;
case 2:
return Platform::Device::ACCESS_16BIT;
default:
return Platform::Device::ACCESS_32BIT;
}
}
static Genode::List<Pci_driver> & _drivers()
{
static Genode::List<Pci_driver> _list;
return _list;
}
public:
Pci_driver(pci_driver *drv, Platform::Device_capability cap,
pci_device_id const * id)
: _drv(drv), _cap(cap), _id(id), _dev(0)
{
if (!_probe())
throw -1;
}
~Pci_driver()
{
if (!_dev)
return;
_drivers().remove(this);
destroy(Genode::env()->heap(), _dev);
}
/**
* Read/write data from/to config space
*/
template <typename T>
void config_read(unsigned int devfn, T *val)
{
Platform::Device_client client(_cap);
*val = client.config_read(devfn, _access_size(*val));
}
template <typename T>
void config_write(unsigned int devfn, T val)
{
Platform::Device_client client(_cap);
client.config_write(devfn, val, _access_size(val));
}
static Genode::Irq_session_capability irq_cap(unsigned irq)
{
for (Pci_driver *d = _drivers().first(); d; d = d->next()) {
if (d->_dev && d->_dev->irq != irq)
continue;
Platform::Device_client client(d->_cap);
return client.irq(0);
}
return Genode::Irq_session_capability();
}
static Genode::Io_mem_session_capability io_mem(resource_size_t phys) {
for (Pci_driver *d = _drivers().first(); d; d = d->next()) {
if (!d->_dev)
continue;
unsigned bar = 0;
for (; bar < PCI_ROM_RESOURCE; bar++) {
if ((pci_resource_flags(d->_dev, bar) & IORESOURCE_MEM) &&
(pci_resource_start(d->_dev, bar) == phys))
break;
}
if (bar >= PCI_ROM_RESOURCE)
continue;
Platform::Device_client client(d->_cap);
return client.io_mem(bar);
}
PERR("Device using i/o memory of address %zx is unknown", phys);
return Genode::Io_mem_session_capability();
}
template <typename POD, bool READ = true>
static POD port_io(unsigned port, POD val = 0)
{
for (Pci_driver *d = _drivers().first(); d; d = d->next()) {
if (!d->_dev)
continue;
if (READ && d->_port.in<POD>(port, &val))
return val;
else if (!READ && d->_port.out<POD>(port, val))
return (POD)~0;
}
return (POD)~0;
}
};
/********************************
** Backend memory definitions **
********************************/
struct Memory_object_base : Genode::Object_pool<Memory_object_base>::Entry
{
Memory_object_base(Genode::Ram_dataspace_capability cap)
: Genode::Object_pool<Memory_object_base>::Entry(cap) {}
virtual ~Memory_object_base() {};
virtual void free() = 0;
Genode::Ram_dataspace_capability ram_cap()
{
using namespace Genode;
return reinterpret_cap_cast<Ram_dataspace>(cap());
}
};
struct Ram_object : Memory_object_base
{
Ram_object(Genode::Ram_dataspace_capability cap)
: Memory_object_base(cap) {}
void free();
};
struct Dma_object : Memory_object_base
{
Dma_object(Genode::Ram_dataspace_capability cap)
: Memory_object_base(cap) {}
void free();
};
/*********************
** Linux interface **
*********************/
static Platform::Connection pci;
static Genode::Object_pool<Memory_object_base> memory_pool;
int pci_register_driver(struct pci_driver *drv)
{
lx_log(DEBUG_PCI, "DRIVER name: %s", drv->name);
drv->driver.name = drv->name;
pci_device_id const *id = drv->id_table;
if (!id)
return -ENODEV;
using namespace Genode;
bool found = false;
while (id->class_ || id->class_mask || id->class_) {
if (id->class_ == (unsigned)PCI_ANY_ID) {
lx_log(DEBUG_PCI, "Skipping PCI_ANY_ID device class");
id++;
continue;
}
Genode::env()->parent()->upgrade(pci.cap(), "ram_quota=4096");
Platform::Device_capability cap = pci.first_device(id->class_,
id->class_mask);
while (cap.valid()) {
if (DEBUG_PCI) {
uint8_t bus, dev, func;
Platform::Device_client client(cap);
client.bus_address(&bus, &dev, &func);
lx_log(DEBUG_PCI, "bus: %x dev: %x func: %x", bus, dev, func);
}
Pci_driver *pci_drv = 0;
try {
/* probe device */
pci_drv = new (env()->heap()) Pci_driver(drv, cap, id);
pci.on_destruction(Platform::Connection::KEEP_OPEN);
found = true;
} catch (Platform::Device::Quota_exceeded) {
Genode::env()->parent()->upgrade(pci.cap(), "ram_quota=4096");
continue;
} catch (...) {
destroy(env()->heap(), pci_drv);
pci_drv = 0;
}
Platform::Device_capability free_up = cap;
try {
cap = pci.next_device(cap, id->class_, id->class_mask);
} catch (Platform::Session::Out_of_metadata) {
Genode::env()->parent()->upgrade(pci.cap(), "ram_quota=4096");
cap = pci.next_device(cap, id->class_, id->class_mask);
}
if (!pci_drv)
pci.release_device(free_up);
}
id++;
}
return found ? 0 : -ENODEV;
}
size_t pci_resource_start(struct pci_dev *dev, unsigned bar)
{
if (bar >= DEVICE_COUNT_RESOURCE)
return 0;
return dev->resource[bar].start;
}
size_t pci_resource_len(struct pci_dev *dev, unsigned bar)
{
size_t start = pci_resource_start(dev, bar);
if (!start)
return 0;
return (dev->resource[bar].end - start) + 1;
}
unsigned int pci_resource_flags(struct pci_dev *dev, unsigned bar)
{
if (bar >= DEVICE_COUNT_RESOURCE)
return 0;
return dev->resource[bar].flags;
}
int pci_bus_read_config_byte(struct pci_bus *bus, unsigned int, int where, u8 *val)
{
Pci_driver *drv = (Pci_driver *)bus;
drv->config_read(where, val);
lx_log(DEBUG_PCI, "READ %p: where: %x val: %x", drv, where, *val);
return 0;
}
int pci_bus_read_config_word(struct pci_bus *bus, unsigned int, int where, u16 *val)
{
Pci_driver *drv = (Pci_driver *)bus;
drv->config_read(where, val);
lx_log(DEBUG_PCI, "READ %p: where: %x val: %x", drv, where, *val);
return 0;
}
int pci_bus_write_config_word(struct pci_bus *bus, unsigned int, int where, u16 val)
{
Pci_driver *drv = (Pci_driver *)bus;
lx_log(DEBUG_PCI, "WRITE %p: where: %x val: %x", drv, where, val);
drv->config_write(where, val);
return 0;
}
int pci_bus_write_config_byte(struct pci_bus *bus, unsigned int, int where, u8 val)
{
Pci_driver *drv = (Pci_driver *)bus;
lx_log(DEBUG_PCI, "WRITE %p: where: %x val: %x", drv, where, val);
drv->config_write(where, val);
return 0;
}
const char *pci_name(const struct pci_dev *pdev)
{
/* simply return driver name */
return "dummy";
}
void Ram_object::free() { Genode::env()->ram_session()->free(ram_cap()); }
void Dma_object::free() { pci.free_dma_buffer(ram_cap()); }
Genode::Ram_dataspace_capability
Backend_memory::alloc(Genode::addr_t size, Genode::Cache_attribute cached)
{
using namespace Genode;
Memory_object_base *o;
Genode::Ram_dataspace_capability cap;
if (cached == CACHED) {
cap = env()->ram_session()->alloc(size);
o = new (env()->heap()) Ram_object(cap);
} else {
size_t donate = size;
cap = Genode::retry<Platform::Session::Out_of_metadata>(
[&] () { return pci.alloc_dma_buffer(size); },
[&] () {
char quota[32];
Genode::snprintf(quota, sizeof(quota), "ram_quota=%zd",
donate);
Genode::env()->parent()->upgrade(pci.cap(), quota);
donate = donate * 2 > size ? 4096 : donate * 2;
});
o = new (env()->heap()) Dma_object(cap);
}
memory_pool.insert(o);
return cap;
}
void Backend_memory::free(Genode::Ram_dataspace_capability cap)
{
using namespace Genode;
Memory_object_base *object;
auto lambda = [&] (Memory_object_base *o) {
object = o;
if (object) {
object->free();
memory_pool.remove(object);
}
};
memory_pool.apply(cap, lambda);
destroy(env()->heap(), object);
}
/**********************
** asm-generic/io.h **
**********************/
void outb(u8 value, u32 port) { Pci_driver::port_io<u8, false>(port, value); }
void outw(u16 value, u32 port) { Pci_driver::port_io<u16, false>(port, value); }
void outl(u32 value, u32 port) { Pci_driver::port_io<u32, false>(port, value); }
u8 inb(u32 port) { return Pci_driver::port_io<u8>(port); }
u16 inw(u32 port) { return Pci_driver::port_io<u16>(port); }
u32 inl(u32 port) { return Pci_driver::port_io<u32>(port); }
/*****************************************
** Platform specific irq cap discovery **
*****************************************/
Genode::Irq_session_capability platform_irq_activate(int irq)
{
return Pci_driver::irq_cap(irq);
}
/******************
** MMIO regions **
******************/
class Mem_range : public Genode::Io_mem_session_client
{
private:
Genode::Io_mem_dataspace_capability _ds;
Genode::addr_t _vaddr;
public:
Mem_range(Genode::addr_t base,
Genode::Io_mem_session_capability io_cap)
:
Io_mem_session_client(io_cap), _ds(dataspace()), _vaddr(0UL)
{
_vaddr = Genode::env()->rm_session()->attach(_ds);
_vaddr |= base & 0xfffUL;
}
Genode::addr_t vaddr() const { return _vaddr; }
};
void *ioremap(resource_size_t phys_addr, unsigned long size)
{
Mem_range * io_mem = new (Genode::env()->heap()) Mem_range(phys_addr, Pci_driver::io_mem(phys_addr));
if (io_mem->vaddr())
return (void *)io_mem->vaddr();
PERR("Failed to request I/O memory: [%zx,%lx)", phys_addr,
phys_addr + size);
return nullptr;
}

View File

@ -19,13 +19,15 @@
#include <usb_session/rpc_object.h>
#include <util/list.h>
#include <extern_c_begin.h>
#include <lx_emul.h>
#include <lx_emul/extern_c_begin.h>
#include <linux/usb.h>
#include "raw.h"
#include "lx_emul.h"
#include <extern_c_end.h>
#include <lx_emul/extern_c_end.h>
#include <signal.h>
#include <lx_kit/scheduler.h>
using namespace Genode;
extern "C" int usb_set_configuration(struct usb_device *dev, int configuration);
@ -109,6 +111,11 @@ struct Device : List<Device>::Element
Genode::snprintf(buf, sizeof(buf), "0x%4x", dev);
xml.attribute("dev", buf);
usb_interface *iface = d->interface(0);
Genode::snprintf(buf, sizeof(buf), "0x%02x",
iface->cur_altsetting->desc.bInterfaceClass);
xml.attribute("class", buf);
});
}
});
@ -157,7 +164,7 @@ class Usb::Worker
Session::Tx::Sink *_sink;
Device *_device = nullptr;
Signal_context_capability _sigh_ready;
Routine *_routine = nullptr;
Lx::Task *_task = nullptr;
unsigned _p_in_flight = 0;
bool _device_ready = false;
@ -453,8 +460,9 @@ class Usb::Worker
void _wait_for_device()
{
_wait_event(_device);
_wait_event(_device->udev->actconfig);
wait_queue_head_t wait;
_wait_event(wait, _device);
_wait_event(wait, _device->udev->actconfig);
if (_sigh_ready.valid())
Signal_transmitter(_sigh_ready).submit(1);
@ -469,24 +477,20 @@ class Usb::Worker
{
/* wait for device to become ready */
init_completion(&_packet_avail);
_wait_for_device();
while (true) {
wait_for_completion(&_packet_avail);
_dispatch();
Routine::schedule_all();
}
}
public:
static int run(void *worker)
static void run(void *worker)
{
Worker *w = static_cast<Worker *>(worker);
w->_wait();
return 0;
}
Worker(Session::Tx::Sink *sink)
@ -495,17 +499,23 @@ class Usb::Worker
void start()
{
if (!_routine) {
_routine = Routine::add(run, this, "worker");
Routine::schedule_all();
if (!_task) {
_task = new (Genode::env()->heap()) Lx::Task(run, this, "raw_worker",
Lx::Task::PRIORITY_2,
Lx::scheduler());
if (!Lx::scheduler().active()) {
Lx::scheduler().schedule();
}
}
}
void stop()
{
if (_routine)
Routine::remove(_routine);
_routine = nullptr;
if (_task) {
Lx::scheduler().remove(_task);
destroy(Genode::env()->heap(), _task);
_task = nullptr;
}
}
void packet_avail() { ::complete(&_packet_avail); }
@ -551,6 +561,7 @@ class Usb::Session_component : public Session_rpc_object,
void _receive(unsigned)
{
_worker.packet_avail();
Lx::scheduler().schedule();
}
public:
@ -852,6 +863,12 @@ int raw_notify(struct notifier_block *nb, unsigned long action, void *data)
{
struct usb_device *udev = (struct usb_device*)data;
if (verbose_raw)
PDBG("RAW: %s vendor: %04x product: %04x\n",
action == USB_DEVICE_ADD ? "Add" : "Remove",
udev->descriptor.idVendor, udev->descriptor.idProduct);
switch (action) {
case USB_DEVICE_ADD:

View File

@ -1,300 +0,0 @@
/*
* \brief Signal context for completions and events
* \author Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
* \date 2012-05-23
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <signal.h>
#include <extern_c_begin.h>
#include <lx_emul.h>
#include <extern_c_end.h>
static Signal_helper *_signal = 0;
/**
* Context for events
*/
class Event_context
{
private:
Genode::Signal_rpc_member<Event_context> _dispatcher;
void _handle(unsigned) {
Routine::schedule_all(); }
Event_context()
: _dispatcher(_signal->ep(), *this, &Event_context::_handle) {
_signal->sender().context(_dispatcher); }
public:
static Event_context *e()
{
static Event_context _e;
return &_e;
}
void submit() {
_signal->sender().submit(); }
char const *debug() { return "Event_context"; }
};
void Event::init(Server::Entrypoint &ep) {
_signal = new (Genode::env()->heap()) Signal_helper(ep); }
/**
* Delayed work
*/
class Work : public Genode::List<Work>::Element
{
private:
void *_work;
enum Type { NORMAL, DELAYED, TASKLET } _type;
static Genode::List<Work> *_list()
{
static Genode::List<Work> _l;
return &_l;
}
public:
Work(delayed_work *work) : _work(work), _type(DELAYED) { }
Work(work_struct *work) : _work(work), _type(NORMAL) { }
Work(tasklet_struct *work) : _work(work), _type(TASKLET) { }
template <typename WORK>
static void schedule(WORK *work)
{
if (work->pending)
return;
work->pending = 1;
_list()->insert(new (Genode::env()->heap()) Work(work));
}
static void exec()
{
while (_list()->first()) {
Work *w = _list()->first();
_list()->remove(w);
switch (w->_type) {
case NORMAL:
{
work_struct *work = static_cast<work_struct *>(w->_work);
work->func(work);
work->pending = 0;
}
break;
case DELAYED:
{
delayed_work *work = static_cast<delayed_work *>(w->_work);
work->work.func(&(work)->work);
work->pending = 0;
}
break;
case TASKLET:
{
tasklet_struct *tasklet = static_cast<tasklet_struct *>(w->_work);
tasklet->func(tasklet->data);
tasklet->pending = 0;
}
break;
}
destroy(Genode::env()->heap(), w);
}
}
};
/************************
** linux/completion.h **
************************/
void __wake_up() { Routine::schedule_all(); }
void __wait_event()
{
/* schedule work first */
Work::exec();
/* schedule other routines or wait for signals */
Service_handler::s()->process();
}
void init_completion(struct completion *work)
{
lx_log(DEBUG_COMPLETION, "New completion %p", work);
work->done = 0;
}
void complete(struct completion *work)
{
lx_log(DEBUG_COMPLETION, "%p", work);
work->done = 1;
/* send signal */
Event_context::e()->submit();
}
void complete_and_exit(struct completion *work, long code)
{
lx_log(DEBUG_COMPLETION, "%p", work);
complete(work);
Routine::remove();
}
static void __wait_completion(struct completion *work)
{
while (!work->done)
__wait_event();
work->done = 0;
}
static unsigned long
__wait_completion_timeout(struct completion *work, unsigned long timeout)
{
unsigned long _j = jiffies + timeout;
while (!work->done) {
__wait_event();
if (_j <= jiffies) {
lx_log(1, "Timeout");
return 0;
}
}
work->done = 0;
return _j - jiffies;
}
unsigned long wait_for_completion_timeout(struct completion *work,
unsigned long timeout)
{
lx_log(DEBUG_COMPLETION, "%p state: %u timeout: %lu", work, work->done, timeout);
return __wait_completion_timeout(work, timeout);
}
int wait_for_completion_interruptible(struct completion *work)
{
lx_log(DEBUG_COMPLETION, "%p state: %u", work, work->done);
__wait_completion(work);
return 0;
}
long wait_for_completion_interruptible_timeout(struct completion *work,
unsigned long timeout)
{
lx_log(DEBUG_COMPLETION, "%p state: %u", work, work->done);
__wait_completion(work);
return 1;
}
void wait_for_completion(struct completion *work)
{
lx_log(DEBUG_COMPLETION, "%p state: %u", work, work->done);
__wait_completion(work);
}
/*******************
** linux/timer.h **
*******************/
signed long schedule_timeout_uninterruptible(signed long timeout)
{
lx_log(DEBUG_COMPLETION, "%ld\n", timeout);
__wait_event();
return 0;
}
int wake_up_process(struct task_struct *tsk)
{
Routine::schedule_all();
return 0;
}
/***********************
** linux/workquque.h **
***********************/
int schedule_delayed_work(struct delayed_work *work, unsigned long delay)
{
Work::schedule(work);
return 0;
}
int schedule_work(struct work_struct *work)
{
Work::schedule(work);
return 1;
}
bool queue_delayed_work(struct workqueue_struct *wq,
struct delayed_work *dwork, unsigned long delay)
{
Work::schedule(dwork);
return true;
}
/***********************
** linux/interrupt.h **
***********************/
void tasklet_init(struct tasklet_struct *t, void (*f)(unsigned long), unsigned long d)
{
t->func = f;
t->data = d;
t->pending = 0;
}
void tasklet_schedule(struct tasklet_struct *tasklet)
{
Work::schedule(tasklet);
}
void tasklet_hi_schedule(struct tasklet_struct *tasklet)
{
/*
* High priority, execute immediately
*/
tasklet->func(tasklet->data);
}

View File

@ -1,193 +0,0 @@
/*
* \brief Signal context for IRQ's
* \author Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
* \date 2012-05-23
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <signal.h>
#include <irq_session/client.h>
#include <extern_c_begin.h>
#include <lx_emul.h>
#include <extern_c_end.h>
#include <platform.h>
/* our local incarnation of sender and receiver */
static Signal_helper *_signal = 0;
/**
* This contains the Linux-driver handlers
*/
struct Irq_handler : Genode::List<Irq_handler>::Element
{
void *dev; /* Linux device */
irq_handler_t handler; /* Linux handler */
Irq_handler(void *dev, irq_handler_t handler)
: dev(dev), handler(handler) { }
};
/**
* Signal context for IRQs
*/
class Irq_context : public Genode::List<Irq_context>::Element
{
private:
typedef Genode::List<Irq_context>::Element LE;
unsigned int _irq; /* IRQ number */
Genode::List<Irq_handler> _handler_list; /* List of registered handlers */
Genode::Signal_rpc_member<Irq_context> _dispatcher;
Genode::Irq_session_capability _irq_cap;
Genode::Irq_session_client _irq_client;
static Genode::List<Irq_context> *_list()
{
static Genode::List<Irq_context> _l;
return &_l;
}
/**
* Find context for given IRQ number
*/
static Irq_context *_find_ctx(unsigned int irq)
{
for (Irq_context *i = _list()->first(); i; i = i->LE::next())
if (i->_irq == irq)
return i;
return 0;
}
/**
* Call one IRQ handler
*/
inline bool _handle_one(Irq_handler *h)
{
bool handled = false;
/*
* It might be that the next interrupt triggers right after the
* device has acknowledged the IRQ. To reduce per-IRQ context
* switches, we merge up to 'MAX_MERGED_IRQS' calls to the
* interrupt handler.
*/
enum { MAX_MERGED_IRQS = 8 };
for (unsigned i = 0; i < MAX_MERGED_IRQS; i++) {
if (h->handler(_irq, h->dev) != IRQ_HANDLED)
break;
handled = true;
}
return handled;
}
/**
* Call all handlers registered for this context
*/
bool _handle()
{
bool handled = false;
/* report IRQ to all clients */
for (Irq_handler *h = _handler_list.first(); h; h = h->next())
if ((handled = _handle_one(h))) {
lx_log(DEBUG_IRQ, "IRQ: %u ret: %u h: %p dev: %p", _irq, handled, h->handler, h->dev);
break;
}
/* ack interrupt */
_irq_client.ack_irq();
if (handled)
Routine::schedule_all();
return handled;
}
void _handle(unsigned) { _handle(); }
public:
Irq_context(unsigned int irq)
: _irq(irq),
_dispatcher(_signal->ep(), *this, &Irq_context::_handle),
_irq_cap(platform_irq_activate(_irq)),
_irq_client(_irq_cap)
{
if (!_irq_cap.valid()) {
PERR("Interrupt %d attach failed", irq);
return;
}
_irq_client.sigh(_dispatcher);
_irq_client.ack_irq();
_list()->insert(this);
}
const char *debug() { return "Irq_context"; }
/**
* Request an IRQ
*/
static void request_irq(unsigned int irq, irq_handler_t handler, void *dev)
{
Irq_handler *h = new(Genode::env()->heap()) Irq_handler(dev, handler);
Irq_context *ctx = _find_ctx(irq);
/* if this IRQ is not registered */
if (!ctx)
ctx = new (Genode::env()->heap()) Irq_context(irq);
/* register Linux handler */
ctx->_handler_list.insert(h);
}
static bool check_irq()
{
bool handled = false;
for (Irq_context *i = _list()->first(); i; i = i->LE::next())
handled |= i->_handle();
return handled;
}
};
void Irq::init(Server::Entrypoint &ep) {
_signal = new (Genode::env()->heap()) Signal_helper(ep); }
void Irq::check_irq()
{
Irq_context::check_irq();
}
/***********************
** linux/interrupt.h **
***********************/
int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
const char *name, void *dev)
{
lx_log(DEBUG_IRQ, "Request irq %u handler %p", irq, handler);
Irq_context::request_irq(irq, handler, dev);
return 0;
}

View File

@ -1,395 +0,0 @@
/*
* \brief Signal context for timer events
* \author Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
* \date 2012-05-23
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/env.h>
#include <base/printf.h>
#include <base/tslab.h>
#include <timer_session/connection.h>
#include <util/volatile_object.h>
/*
* The Genode headers must be included before any Linux header. Otherwise,
* the 'SUCCESS' macro defined in scsi/scsi_host.h collides with Genode's
* 'Rpc_exception_code::SUCCESS' enum value.
*/
#include "signal.h"
#include "list.h"
#include <extern_c_begin.h>
#include <lx_emul.h>
#include <extern_c_end.h>
unsigned long jiffies;
static void handler(void *timer);
namespace Lx {
class Timer;
}
static int run_timer(void *);
/**
* Lx::Timer
*/
class Lx::Timer
{
public:
/**
* Context encapsulates a regular linux timer_list
*/
struct Context : public Lx::List<Context>::Element
{
enum { INVALID_TIMEOUT = ~0UL };
enum Type { LIST, HR };
Type type;
void *timer;
bool pending { false };
unsigned long timeout { INVALID_TIMEOUT }; /* absolute in jiffies */
bool programmed { false };
Context(struct timer_list *timer) : type(LIST), timer(timer) { }
Context(struct hrtimer *timer) : type(HR), timer(timer) { }
void expires(unsigned long e)
{
if (type == LIST)
static_cast<timer_list *>(timer)->expires = e;
}
void function()
{
switch (type) {
case LIST:
{
timer_list *t = static_cast<timer_list *>(timer);
if (t->function)
t->function(t->data);
}
break;
case HR:
{
hrtimer *t = static_cast<hrtimer *>(timer);
if (t->function)
t->function(t);
}
break;
}
}
};
private:
::Timer::Connection _timer_conn;
Lx::List<Context> _list;
Routine *_timer_task = Routine::add(run_timer, nullptr, "timer");
Genode::Signal_rpc_member<Lx::Timer> _dispatcher;
Genode::Tslab<Context, 32 * sizeof(Context)> _timer_alloc;
public:
bool ready { true };
private:
/**
* Lookup local timer
*/
Context *_find_context(void const *timer)
{
for (Context *c = _list.first(); c; c = c->next())
if (c->timer == timer)
return c;
return 0;
}
/**
* Program the first timer in the list
*
* The first timer is programmed if the 'programmed' flag was not set
* before. The second timer is flagged as not programmed as
* 'Timer::trigger_once' invalidates former registered one-shot
* timeouts.
*/
void _program_first_timer()
{
Context *ctx = _list.first();
if (!ctx)
return;
if (ctx->programmed)
return;
/* calculate relative microseconds for trigger */
unsigned long us = ctx->timeout > jiffies ?
jiffies_to_msecs(ctx->timeout - jiffies) * 1000 : 0;
_timer_conn.trigger_once(us);
ctx->programmed = true;
/* possibly programmed successor must be reprogrammed later */
if (Context *next = ctx->next())
next->programmed = false;
}
/**
* Schedule timer
*
* Add the context to the scheduling list depending on its timeout
* and reprogram the first timer.
*/
void _schedule_timer(Context *ctx, unsigned long expires)
{
_list.remove(ctx);
ctx->timeout = expires;
ctx->pending = true;
ctx->programmed = false;
/*
* Also write the timeout value to the expires field in
* struct timer_list because the checks
* it directly.
*/
ctx->expires(expires);
Context *c;
for (c = _list.first(); c; c = c->next())
if (ctx->timeout <= c->timeout)
break;
_list.insert_before(ctx, c);
_program_first_timer();
}
/**
* Handle trigger_once signal
*/
void _handle(unsigned)
{
ready = true;
Routine::schedule_all();
}
public:
/**
* Constructor
*/
Timer(Server::Entrypoint &ep)
:
_dispatcher(ep, *this, &Lx::Timer::_handle),
_timer_alloc(Genode::env()->heap())
{
_timer_conn.sigh(_dispatcher);
}
/**
* Add new linux timer
*/
template <typename TIMER>
void add(TIMER *timer)
{
Context *t = new (&_timer_alloc) Context(timer);
_list.append(t);
}
/**
* Delete linux timer
*/
int del(void *timer)
{
Context *ctx = _find_context(timer);
/**
* If the timer expired it was already cleaned up after its
* execution.
*/
if (!ctx)
return 0;
int rv = ctx->timeout != Context::INVALID_TIMEOUT ? 1 : 0;
_list.remove(ctx);
destroy(&_timer_alloc, ctx);
return rv;
}
/**
* Initial scheduling of linux timer
*/
int schedule(void *timer, unsigned long expires)
{
Context *ctx = _find_context(timer);
if (!ctx) {
PERR("schedule unknown timer %p", timer);
return -1; /* XXX better use 0 as rv? */
}
/*
* If timer was already active return 1, otherwise 0. The return
* value is needed by mod_timer().
*/
int rv = ctx->timeout != Context::INVALID_TIMEOUT ? 1 : 0;
_schedule_timer(ctx, expires);
return rv;
}
/**
* Schedule next linux timer
*/
void schedule_next() { _program_first_timer(); }
/**
* Check if the timer is currently pending
*/
bool pending(void const *timer)
{
Context *ctx = _find_context(timer);
if (!ctx) {
return false;
}
return ctx->pending;
}
Context *find(void const *timer) {
return _find_context(timer); }
/**
* Update jiffie counter
*/
void update_jiffies()
{
jiffies = msecs_to_jiffies(_timer_conn.elapsed_ms());
}
/**
* Get first timer context
*/
Context* first() { return _list.first(); }
};
Genode::Lazy_volatile_object<Lx::Timer> _lx_timer;
void Timer::init(Server::Entrypoint &ep)
{
_lx_timer.construct(ep);
/* initialize value explicitly */
jiffies = 0UL;
}
void Timer::update_jiffies()
{
_lx_timer->update_jiffies();
}
static int run_timer(void *)
{
while (1) {
_wait_event(_lx_timer->ready);
while (Lx::Timer::Context *ctx = _lx_timer->first()) {
if (ctx->timeout > jiffies)
break;
ctx->function();
_lx_timer->del(ctx->timer);
}
_lx_timer->ready = false;
}
return 0;
}
/*******************
** linux/timer.h **
*******************/
void init_timer(struct timer_list *timer) { }
int mod_timer(struct timer_list *timer, unsigned long expires)
{
if (!_lx_timer->find(timer))
_lx_timer->add(timer);
return _lx_timer->schedule(timer, expires);
}
void setup_timer(struct timer_list *timer,void (*function)(unsigned long),
unsigned long data)
{
timer->function = function;
timer->data = data;
}
int timer_pending(const struct timer_list * timer)
{
bool pending = _lx_timer->pending(timer);
lx_log(DEBUG_TIMER, "Pending %p %u", timer, pending);
return pending;
}
int del_timer(struct timer_list *timer)
{
lx_log(DEBUG_TIMER, "Delete timer %p", timer);
int rv = _lx_timer->del(timer);
_lx_timer->schedule_next();
return rv;
}
/*********************
** linux/hrtimer.h **
*********************/
void hrtimer_init(struct hrtimer *timer, clockid_t clock_id, enum hrtimer_mode mode) { }
int hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
unsigned long delta_ns, const enum hrtimer_mode mode)
{
unsigned long expires = tim.tv64 / (NSEC_PER_MSEC * HZ);
if (!_lx_timer->find(timer))
_lx_timer->add(timer);
lx_log(DEBUG_TIMER, "HR: e: %lu j %lu", jiffies, expires);
return _lx_timer->schedule(timer, expires);
}
int hrtimer_cancel(struct hrtimer *timer)
{
int rv = _lx_timer->del(timer);
_lx_timer->schedule_next();
return rv;
}

View File

@ -12,11 +12,7 @@
*/
#include <os/attached_io_mem_dataspace.h>
#include <lx/extern_c_begin.h>
#include <lx_emul.h>
#include <lx/extern_c_end.h>
#define to_platform_driver(drv) (container_of((drv), struct platform_driver, \
@ -198,20 +194,20 @@ void platform_set_drvdata(struct platform_device *pdev, void *data)
** asm-generic/io.h **
**********************/
void *_ioremap(resource_size_t phys_addr, unsigned long size, int wc)
void *_ioremap(phys_addr_t phys_addr, unsigned long size, int wc)
{
try {
Genode::Attached_io_mem_dataspace *ds = new(Genode::env()->heap())
Genode::Attached_io_mem_dataspace(phys_addr, size, !!wc);
return ds->local_addr<void>();
} catch (...) {
panic("Failed to request I/O memory: [%zx,%lx)", phys_addr, phys_addr + size);
panic("Failed to request I/O memory: [%lx,%lx)", phys_addr, phys_addr + size);
return 0;
}
}
void *ioremap(resource_size_t offset, unsigned long size)
void *ioremap(phys_addr_t offset, unsigned long size)
{
return _ioremap(offset, size, 0);
}

View File

@ -0,0 +1,45 @@
/**
* \brief ARM specific implemenations used on all SOCs
* \author Sebastian Sumpf
* \date 2016-04-25
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/env.h>
#include <lx_emul/irq.h>
#include <lx_kit/backend_alloc.h>
#include <lx_kit/irq.h>
/****************************
** lx_kit/backend_alloc.h **
****************************/
Genode::Ram_dataspace_capability
Lx::backend_alloc(Genode::addr_t size, Genode::Cache_attribute cached) {
return Genode::env()->ram_session()->alloc(size, cached); }
void Lx::backend_free(Genode::Ram_dataspace_capability cap) {
return Genode::env()->ram_session()->free(cap); }
/***********************
** linux/interrupt.h **
***********************/
extern "C" int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
const char *name, void *dev)
{
Lx::Irq::irq().request_irq(Platform::Device::create(irq), handler, dev);
return 0;
}

View File

@ -21,21 +21,10 @@
#include <irq_session/connection.h>
#include <util/mmio.h>
/*
* The Genode headers must be included before any Linux header. Otherwise,
* the 'SUCCESS' macro defined in scsi/scsi_host.h collides with Genode's
* 'Rpc_exception_code::SUCCESS' enum value.
*/
#include <platform.h>
#include <platform/platform.h>
/* Emulation */
#include <extern_c_begin.h>
#include <lx_emul.h>
#include <extern_c_end.h>
#include <platform.h>
/* Linux */
#include <linux/platform_data/dwc3-exynos.h>
using namespace Genode;
@ -60,7 +49,6 @@ static resource _dwc3[] =
{ DWC3_IRQ, DWC3_IRQ, "dwc3-irq", IORESOURCE_IRQ },
};
static struct dwc3_exynos_data _dwc3_data;
/**
* EHCI controller
@ -299,8 +287,7 @@ extern "C" void module_usbnet_init();
extern "C" void module_asix_driver_init();
extern "C" void module_ax88179_178a_driver_init();
extern "C" void module_dwc3_driver_init();
extern "C" void module_xhci_hcd_init();
extern "C" void module_xhci_plat_init();
extern "C" void module_asix_init();
@ -337,7 +324,7 @@ void xhci_setup(Services *services)
module_ax88179_178a_driver_init();
module_dwc3_driver_init();
module_xhci_hcd_init();
module_xhci_plat_init();
arndale_xhci_init();
@ -347,7 +334,6 @@ void xhci_setup(Services *services)
pdev->id = 0;
pdev->num_resources = 2;
pdev->resource = _dwc3;
pdev->dev.platform_data = &_dwc3_data;
/*needed for DMA buffer allocation. See 'hcd_buffer_alloc' in 'buffer.c' */
static u64 dma_mask = ~(u64)0;

View File

@ -26,10 +26,7 @@
#include <gpio_session/connection.h>
/* Emulation */
#include <platform/platform.h>
#include <extern_c_begin.h>
#include <lx_emul.h>
#include <extern_c_end.h>
#include <platform.h>
#include <usb_masks.h>

View File

@ -11,7 +11,6 @@
* under the terms of the GNU General Public License version 2.
*/
#include <platform/platform.h>
#include <platform.h>
#include <drivers/board_base.h>
@ -20,9 +19,7 @@
#include <irq_session/connection.h>
#include <util/mmio.h>
#include <extern_c_begin.h>
#include <lx_emul.h>
#include <extern_c_end.h>
#include <linux/platform_data/usb-omap.h>

View File

@ -18,12 +18,8 @@
#include <platform_session/connection.h>
/* emulation */
#include <platform/platform.h>
#include <platform.h>
#include <extern_c_begin.h>
#include <lx_emul.h>
#include <extern_c_end.h>
/* dwc-otg */
#define new new_
@ -115,7 +111,6 @@ DUMMY(-1, dwc_otg_pcd_get_rmwkup_enable);
DUMMY(-1, dwc_otg_pcd_initiate_srp);
DUMMY(-1, pcd_remove);
SILENT_DUMMY( 0, pcd_init);
DUMMY(-1, printk_once);
/************************************************************************
@ -124,6 +119,8 @@ DUMMY(-1, printk_once);
void local_fiq_disable() { }
void local_fiq_enable() { }
extern "C" void fiq_fsm_spin_lock(void *lock) { }
extern "C" void fiq_fsm_spin_unlock(void *lock) { }
int claim_fiq(struct fiq_handler *f) { return 0; }
void set_fiq_regs(struct pt_regs const *regs) { }
void set_fiq_handler(void *start, unsigned int length) { }
@ -140,22 +137,6 @@ unsigned char _dwc_otg_fiq_stub, _dwc_otg_fiq_stub_end;
extern int fiq_enable, fiq_fsm_enable;
/***********************
** linux/workqueue.h **
***********************/
struct workqueue_struct *create_singlethread_workqueue(char *)
{
workqueue_struct *wq = (workqueue_struct *)kzalloc(sizeof(workqueue_struct), 0);
return wq;
}
void destroy_workqueue(struct workqueue_struct *wq) { TRACE; }
bool queue_work(struct workqueue_struct *wq, struct work_struct *work) { TRACE; return 0; }
/***********************
** asm/dma_mapping.h **
***********************/

View File

@ -0,0 +1,203 @@
/**
* \brief PCI device handling
* \author Sebastian Sumpf
* \date 2016-04-25
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <base/allocator.h>
#include <base/entrypoint.h>
#include <base/lock.h>
#include <base/signal.h>
#include <os/config.h>
#include <util/misc_math.h>
#include <lx_emul.h>
#include <lx_kit/irq.h>
#include <lx_kit/pci_dev_registry.h>
#include <lx_kit/mapped_io_mem_range.h>
#include <lx_emul/impl/io.h>
#include <lx_emul/impl/pci_resource.h>
/**
* Quirks
*/
extern "C" void __pci_fixup_quirk_usb_early_handoff(void *data);
/**
* List of pci devices from platform driver
*/
class Pci_dev_list
{
private:
struct Element : public Lx_kit::List<Element>::Element
{
Platform::Device_capability cap;
Element(Platform::Device_capability cap) : cap(cap) { }
};
Lx_kit::List<Element> _pci_caps;
public:
Pci_dev_list()
{
/*
* Functor that is called if the platform driver throws a
* 'Out_of_metadata' exception.
*/
auto handler = [&] () {
Genode::env()->parent()->upgrade(Lx::pci()->cap(),
"ram_quota=4096"); };
/*
* Obtain first device, the operation may exceed the session quota.
* So we use the 'retry' mechanism.
*/
Platform::Device_capability cap;
auto attempt = [&] () { cap = Lx::pci()->first_device(); };
Genode::retry<Platform::Session::Out_of_metadata>(attempt, handler);
/*
* Iterate over the devices of the platform session.
*/
while (cap.valid()) {
_pci_caps.insert(new (Genode::env()->heap()) Element(cap));
/* try next one. Upgrade session * quota on demand.*/
auto attempt = [&] () {
cap = Lx::pci()->next_device(cap);
};
Genode::retry<Platform::Session::Out_of_metadata>(attempt, handler);
}
}
template <typename FUNC>
void for_each_pci_device(FUNC const &func)
{
for (Element *e = _pci_caps.first(); e; e = e->next())
func(e->cap);
}
};
Pci_dev_list *pci_dev_list()
{
static Pci_dev_list _list;
return &_list;
}
extern "C" int pci_register_driver(struct pci_driver *driver)
{
driver->driver.name = driver->name;
pci_device_id const *id_table = driver->id_table;
if (!id_table)
return -ENODEV;
using namespace Genode;
bool found = false;
auto lamda = [&] (Platform::Device_capability cap) {
Platform::Device_client client(cap);
/* request device ID from platform driver */
unsigned const class_code = client.class_code();
/* look if we find the device ID in the driver's 'id_table' */
pci_device_id const *matching_id = nullptr;
for (pci_device_id const *id = id_table; id->device; id++) {
lx_log(DEBUG_PCI,"idclass: %x idclassm: %x devclass %x", id->class_,
id->class_mask, class_code);
/* check for drivers that support any device for a given class */
if (id->device != (unsigned)PCI_ANY_ID || !id->class_mask)
continue;
if ((id->class_ & id->class_mask) == (class_code & id->class_mask)) {
matching_id = id;
break;
}
}
/* skip device that is not handled by driver */
if (!matching_id)
return false;
/* create 'pci_dev' struct for matching device */
Lx::Pci_dev *pci_dev = new (env()->heap()) Lx::Pci_dev(cap);
/* enable ioremap to work */
Lx::pci_dev_registry()->insert(pci_dev);
/* register driver at the 'pci_dev' struct */
pci_dev->dev.driver = &driver->driver;
bool bios_handoff = true;
try {
if (config()->xml_node().attribute("bios_handoff").has_value("no"))
bios_handoff = false;
} catch (...) { }
/*
* This quirk handles device handoff from BIOS, since the BIOS may still
* access the USB controller after bootup. For this the ext cap register of
* the PCI config space is checked
*/
if (bios_handoff)
__pci_fixup_quirk_usb_early_handoff(pci_dev);
/* call probe function of the Linux driver */
if (driver->probe(pci_dev, matching_id)) {
/* if the probing failed, revert the creation of 'pci_dev' */
pci_dev_put(pci_dev);
return false;
}
found = true;
/* multiple device support continue */
return true;
};
pci_dev_list()->for_each_pci_device(lamda);
return found ? 0 : -ENODEV;
}
/***********************
** linux/interrupt.h **
***********************/
int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
const char *name, void *dev)
{
for (Lx::Pci_dev *pci_dev = Lx::pci_dev_registry()->first(); pci_dev; pci_dev = pci_dev->next())
if (pci_dev->irq == irq) {
Lx::Irq::irq().request_irq(pci_dev->client(), handler, dev);
return 0;
}
return -ENODEV;
}

View File

@ -12,7 +12,6 @@
*/
#include <platform.h>
#include <platform/platform.h>
extern "C" void module_ax88179_178a_driver_init();
@ -21,6 +20,7 @@ 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();
extern "C" void module_xhci_pci_init();
void platform_hcd_init(Services *s)
{
@ -29,8 +29,10 @@ void platform_hcd_init(Services *s)
module_ax88179_178a_driver_init();
}
if (s->xhci)
if (s->xhci) {
module_xhci_hcd_init();
module_xhci_pci_init();
}
/* ehci_hcd should always be loaded before uhci_hcd and ohci_hcd, not after */
if (s->ehci) {

View File

@ -17,13 +17,16 @@
#include <util/endian.h>
#include <util/list.h>
#include <extern_c_begin.h>
#include <lx_emul.h>
#include <lx_kit/backend_alloc.h>
#include <lx_kit/scheduler.h>
#include <lx_emul/extern_c_begin.h>
#include <storage/scsi.h>
#include <drivers/usb/storage/usb.h>
#include <extern_c_end.h>
#include <lx_emul/extern_c_end.h>
#include <platform/lx_mem.h>
#include "signal.h"
static Signal_helper *_signal = 0;
@ -125,6 +128,10 @@ class Storage_device : public Genode::List<Storage_device>::Element,
/* send command to host driver */
_sdev->host->hostt->queuecommand(_sdev->host, cmnd);
/* schedule next task if we come from EP */
if (Lx::scheduler().active() == false)
Lx::scheduler().schedule();
}
public:
@ -162,10 +169,10 @@ class Storage_device : public Genode::List<Storage_device>::Element,
bool dma_enabled() { return true; }
Genode::Ram_dataspace_capability alloc_dma_buffer(Genode::size_t size) {
return Backend_memory::alloc(size, Genode::UNCACHED); }
return Lx::backend_alloc(size, Genode::UNCACHED); }
void free_dma_buffer(Genode::Ram_dataspace_capability cap) {
return Backend_memory::free(cap); }
return Lx::backend_free(cap); }
};
@ -191,7 +198,7 @@ static work_struct delayed;
extern "C" void ack_packet(work_struct *work)
{
Block::Packet_descriptor *packet =
static_cast<Block::Packet_descriptor *>(work->data);
(Block::Packet_descriptor *)(work->data);
if (verbose)
PDBG("ACK packet for block: %llu", packet->block_number());

View File

@ -14,6 +14,7 @@
*/
/* Genode includes */
#include <base/entrypoint.h>
#include <base/snprintf.h>
#include <base/tslab.h>
#include <irq_session/client.h>

View File

@ -1,155 +1,167 @@
linux-3.14.5/drivers/hid/hid-cherry.c
linux-3.14.5/drivers/hid/hid-core.c
linux-3.14.5/drivers/hid/hid-generic.c
linux-3.14.5/drivers/hid/hid-ids.h
linux-3.14.5/drivers/hid/hid-input.c
linux-3.14.5/drivers/hid/hid-microsoft.c
linux-3.14.5/drivers/hid/hid-multitouch.c
linux-3.14.5/drivers/hid/usbhid/hid-core.c
linux-3.14.5/drivers/hid/usbhid/hid-quirks.c
linux-3.14.5/drivers/hid/usbhid/usbhid.h
linux-3.14.5/drivers/input/evdev.c
linux-3.14.5/drivers/input/input-compat.h
linux-3.14.5/drivers/input/input-mt.c
linux-3.14.5/drivers/input/input.c
linux-3.14.5/drivers/input/tablet/wacom.h
linux-3.14.5/drivers/input/tablet/wacom_sys.c
linux-3.14.5/drivers/input/tablet/wacom_wac.c
linux-3.14.5/drivers/input/tablet/wacom_wac.h
linux-3.14.5/drivers/net/usb/asix_common.c
linux-3.14.5/drivers/net/usb/asix_devices.c
linux-3.14.5/drivers/net/usb/asix.h
linux-3.14.5/drivers/net/usb/ax88172a.c
linux-3.14.5/drivers/net/usb/ax88179_178a.c
linux-3.14.5/drivers/net/usb/smsc95xx.h
linux-3.14.5/drivers/net/usb/smsc95xx.c
linux-3.14.5/drivers/net/usb/usbnet.c
linux-3.14.5/drivers/scsi/constants.c
linux-3.14.5/drivers/scsi/scsi_logging.h
linux-3.14.5/drivers/scsi/scsi.c
linux-3.14.5/drivers/scsi/scsi_priv.h
linux-3.14.5/drivers/usb/core/buffer.c
linux-3.14.5/drivers/usb/core/config.c
linux-3.14.5/drivers/usb/core/devices.c
linux-3.14.5/drivers/usb/core/driver.c
linux-3.14.5/drivers/usb/core/endpoint.c
linux-3.14.5/drivers/usb/core/file.c
linux-3.14.5/drivers/usb/core/generic.c
linux-3.14.5/drivers/usb/core/hcd.c
linux-3.14.5/drivers/usb/core/hcd-pci.c
linux-3.14.5/drivers/usb/core/hub.h
linux-3.14.5/drivers/usb/core/hub.c
linux-3.14.5/drivers/usb/core/message.c
linux-3.14.5/drivers/usb/core/notify.c
linux-3.14.5/drivers/usb/core/port.c
linux-3.14.5/drivers/usb/core/quirks.c
linux-3.14.5/drivers/usb/core/urb.c
linux-3.14.5/drivers/usb/core/usb.h
linux-3.14.5/drivers/usb/core/usb.c
linux-3.14.5/drivers/usb/dwc3/core.h
linux-3.14.5/drivers/usb/dwc3/core.c
linux-3.14.5/drivers/usb/dwc3/debug.h
linux-3.14.5/drivers/usb/dwc3/gadget.h
linux-3.14.5/drivers/usb/dwc3/host.c
linux-3.14.5/drivers/usb/dwc3/io.h
linux-3.14.5/drivers/usb/dwc3/platform_data.h
linux-3.14.5/drivers/usb/host/ehci-dbg.c
linux-3.14.5/drivers/usb/host/ehci-exynos.c
linux-3.14.5/drivers/usb/host/ehci.h
linux-3.14.5/drivers/usb/host/ehci-hcd.c
linux-3.14.5/drivers/usb/host/ehci-hub.c
linux-3.14.5/drivers/usb/host/ehci-mem.c
linux-3.14.5/drivers/usb/host/ehci-omap.c
linux-3.14.5/drivers/usb/host/ehci-pci.c
linux-3.14.5/drivers/usb/host/ehci-q.c
linux-3.14.5/drivers/usb/host/ehci-sched.c
linux-3.14.5/drivers/usb/host/ehci-sysfs.c
linux-3.14.5/drivers/usb/host/ehci-timer.c
linux-3.14.5/drivers/usb/host/pci-quirks.h
linux-3.14.5/drivers/usb/host/pci-quirks.c
linux-3.14.5/drivers/usb/host/uhci-debug.c
linux-3.14.5/drivers/usb/host/uhci-hcd.h
linux-3.14.5/drivers/usb/host/uhci-hcd.c
linux-3.14.5/drivers/usb/host/uhci-hub.c
linux-3.14.5/drivers/usb/host/uhci-pci.c
linux-3.14.5/drivers/usb/host/uhci-q.c
linux-3.14.5/drivers/usb/host/xhci-dbg.c
linux-3.14.5/drivers/usb/host/xhci-ext-caps.h
linux-3.14.5/drivers/usb/host/xhci.h
linux-3.14.5/drivers/usb/host/xhci-hub.c
linux-3.14.5/drivers/usb/host/xhci-mem.c
linux-3.14.5/drivers/usb/host/xhci.c
linux-3.14.5/drivers/usb/host/xhci-pci.c
linux-3.14.5/drivers/usb/host/xhci-plat.c
linux-3.14.5/drivers/usb/host/xhci-ring.c
linux-3.14.5/drivers/usb/host/xhci-trace.h
linux-3.14.5/drivers/usb/storage/debug.h
linux-3.14.5/drivers/usb/storage/initializers.h
linux-3.14.5/drivers/usb/storage/initializers.c
linux-3.14.5/drivers/usb/storage/option_ms.h
linux-3.14.5/drivers/usb/storage/option_ms.c
linux-3.14.5/drivers/usb/storage/protocol.h
linux-3.14.5/drivers/usb/storage/protocol.c
linux-3.14.5/drivers/usb/storage/scsiglue.h
linux-3.14.5/drivers/usb/storage/scsiglue.c
linux-3.14.5/drivers/usb/storage/sierra_ms.h
linux-3.14.5/drivers/usb/storage/sierra_ms.c
linux-3.14.5/drivers/usb/storage/transport.h
linux-3.14.5/drivers/usb/storage/transport.c
linux-3.14.5/drivers/usb/storage/unusual_alauda.h
linux-3.14.5/drivers/usb/storage/unusual_cypress.h
linux-3.14.5/drivers/usb/storage/unusual_datafab.h
linux-3.14.5/drivers/usb/storage/unusual_devs.h
linux-3.14.5/drivers/usb/storage/unusual_ene_ub6250.h
linux-3.14.5/drivers/usb/storage/unusual_freecom.h
linux-3.14.5/drivers/usb/storage/unusual_isd200.h
linux-3.14.5/drivers/usb/storage/unusual_jumpshot.h
linux-3.14.5/drivers/usb/storage/unusual_karma.h
linux-3.14.5/drivers/usb/storage/unusual_onetouch.h
linux-3.14.5/drivers/usb/storage/unusual_realtek.h
linux-3.14.5/drivers/usb/storage/unusual_sddr09.h
linux-3.14.5/drivers/usb/storage/unusual_sddr55.h
linux-3.14.5/drivers/usb/storage/unusual_usbat.h
linux-3.14.5/drivers/usb/storage/usb.h
linux-3.14.5/drivers/usb/storage/usb.c
linux-3.14.5/drivers/usb/storage/usual-tables.c
linux-3.14.5/drivers/usb/usb-common.c
linux-3.14.5/include/asm-generic/bitops/__ffs.h
linux-3.14.5/include/asm-generic/bitops/non-atomic.h
linux-3.14.5/include/asm-generic/ioctl.h
linux-3.14.5/include/linux/hiddev.h
linux-3.14.5/include/linux/hid.h
linux-3.14.5/include/linux/input.h
linux-3.14.5/include/linux/input/mt.h
linux-3.14.5/include/linux/leds.h
linux-3.14.5/include/linux/list.h
linux-3.14.5/include/linux/mod_devicetable.h
linux-3.14.5/include/linux/netdev_features.h
linux-3.14.5/include/linux/platform_data/dwc3-exynos.h
linux-3.14.5/include/linux/pci_ids.h
linux-3.14.5/include/linux/platform_data/usb-omap.h
linux-3.14.5/include/linux/power_supply.h
linux-3.14.5/include/linux/swab.h
linux-3.14.5/include/linux/usb.h
linux-3.14.5/include/linux/usb_usual.h
linux-3.14.5/include/linux/usb/ch9.h
linux-3.14.5/include/linux/usb/ehci_def.h
linux-3.14.5/include/linux/usb/hcd.h
linux-3.14.5/include/linux/usb/input.h
linux-3.14.5/include/linux/usb/otg.h
linux-3.14.5/include/linux/usb/phy.h
linux-3.14.5/include/linux/usb/quirks.h
linux-3.14.5/include/linux/usb/storage.h
linux-3.14.5/include/linux/usb/usbnet.h
linux-3.14.5/include/scsi/scsi.h
linux-3.14.5/include/scsi/scsi_host.h
linux-3.14.5/include/uapi/asm-generic/ioctl.h
linux-3.14.5/include/uapi/linux/byteorder/little_endian.h
linux-3.14.5/include/uapi/linux/hid.h
linux-3.14.5/include/uapi/linux/input.h
linux-3.14.5/include/uapi/linux/pci_regs.h
linux-3.14.5/include/uapi/linux/stat.h
linux-3.14.5/include/uapi/linux/swab.h
linux-3.14.5/include/uapi/linux/usb/ch11.h
linux-3.14.5/include/uapi/linux/usb/ch9.h
linux-3.14.5/lib/int_sqrt.c
linux-4.4.3/drivers/hid/hid-cherry.c
linux-4.4.3/drivers/hid/hid-core.c
linux-4.4.3/drivers/hid/hid-generic.c
linux-4.4.3/drivers/hid/hid-ids.h
linux-4.4.3/drivers/hid/hid-input.c
linux-4.4.3/drivers/hid/hid-microsoft.c
linux-4.4.3/drivers/hid/hid-multitouch.c
linux-4.4.3/drivers/hid/wacom.h
linux-4.4.3/drivers/hid/wacom_sys.c
linux-4.4.3/drivers/hid/wacom_wac.c
linux-4.4.3/drivers/hid/wacom_wac.h
linux-4.4.3/drivers/hid/usbhid/hid-core.c
linux-4.4.3/drivers/hid/usbhid/hid-quirks.c
linux-4.4.3/drivers/hid/usbhid/usbhid.h
linux-4.4.3/drivers/input/evdev.c
linux-4.4.3/drivers/input/input-compat.h
linux-4.4.3/drivers/input/input-mt.c
linux-4.4.3/drivers/input/input.c
linux-4.4.3/drivers/net/usb/asix_common.c
linux-4.4.3/drivers/net/usb/asix_devices.c
linux-4.4.3/drivers/net/usb/asix.h
linux-4.4.3/drivers/net/usb/ax88172a.c
linux-4.4.3/drivers/net/usb/ax88179_178a.c
linux-4.4.3/drivers/net/usb/smsc95xx.h
linux-4.4.3/drivers/net/usb/smsc95xx.c
linux-4.4.3/drivers/net/usb/usbnet.c
linux-4.4.3/drivers/scsi/constants.c
linux-4.4.3/drivers/scsi/scsi_logging.h
linux-4.4.3/drivers/scsi/scsi.c
linux-4.4.3/drivers/scsi/scsi_priv.h
linux-4.4.3/drivers/usb/common/common.c
linux-4.4.3/drivers/usb/core/buffer.c
linux-4.4.3/drivers/usb/core/config.c
linux-4.4.3/drivers/usb/core/devices.c
linux-4.4.3/drivers/usb/core/driver.c
linux-4.4.3/drivers/usb/core/endpoint.c
linux-4.4.3/drivers/usb/core/file.c
linux-4.4.3/drivers/usb/core/generic.c
linux-4.4.3/drivers/usb/core/hcd.c
linux-4.4.3/drivers/usb/core/hcd-pci.c
linux-4.4.3/drivers/usb/core/hub.h
linux-4.4.3/drivers/usb/core/hub.c
linux-4.4.3/drivers/usb/core/message.c
linux-4.4.3/drivers/usb/core/notify.c
linux-4.4.3/drivers/usb/core/port.c
linux-4.4.3/drivers/usb/core/quirks.c
linux-4.4.3/drivers/usb/core/urb.c
linux-4.4.3/drivers/usb/core/usb.h
linux-4.4.3/drivers/usb/core/usb.c
linux-4.4.3/drivers/usb/dwc3/core.h
linux-4.4.3/drivers/usb/dwc3/core.c
linux-4.4.3/drivers/usb/dwc3/debug.h
linux-4.4.3/drivers/usb/dwc3/dwc3-exynos.c
linux-4.4.3/drivers/usb/dwc3/gadget.h
linux-4.4.3/drivers/usb/dwc3/host.c
linux-4.4.3/drivers/usb/dwc3/io.h
linux-4.4.3/drivers/usb/dwc3/platform_data.h
linux-4.4.3/drivers/usb/dwc3/trace.h
linux-4.4.3/drivers/usb/host/ehci-dbg.c
linux-4.4.3/drivers/usb/host/ehci-exynos.c
linux-4.4.3/drivers/usb/host/ehci.h
linux-4.4.3/drivers/usb/host/ehci-hcd.c
linux-4.4.3/drivers/usb/host/ehci-hub.c
linux-4.4.3/drivers/usb/host/ehci-mem.c
linux-4.4.3/drivers/usb/host/ehci-omap.c
linux-4.4.3/drivers/usb/host/ehci-pci.c
linux-4.4.3/drivers/usb/host/ehci-q.c
linux-4.4.3/drivers/usb/host/ehci-sched.c
linux-4.4.3/drivers/usb/host/ehci-sysfs.c
linux-4.4.3/drivers/usb/host/ehci-timer.c
linux-4.4.3/drivers/usb/host/pci-quirks.h
linux-4.4.3/drivers/usb/host/pci-quirks.c
linux-4.4.3/drivers/usb/host/uhci-debug.c
linux-4.4.3/drivers/usb/host/uhci-hcd.h
linux-4.4.3/drivers/usb/host/uhci-hcd.c
linux-4.4.3/drivers/usb/host/uhci-hub.c
linux-4.4.3/drivers/usb/host/uhci-pci.c
linux-4.4.3/drivers/usb/host/uhci-q.c
linux-4.4.3/drivers/usb/host/xhci-dbg.c
linux-4.4.3/drivers/usb/host/xhci-ext-caps.h
linux-4.4.3/drivers/usb/host/xhci.h
linux-4.4.3/drivers/usb/host/xhci-hub.c
linux-4.4.3/drivers/usb/host/xhci-mem.c
linux-4.4.3/drivers/usb/host/xhci-mvebu.h
linux-4.4.3/drivers/usb/host/xhci-rcar.h
linux-4.4.3/drivers/usb/host/xhci.c
linux-4.4.3/drivers/usb/host/xhci-pci.c
linux-4.4.3/drivers/usb/host/xhci-plat.c
linux-4.4.3/drivers/usb/host/xhci-ring.c
linux-4.4.3/drivers/usb/host/xhci-trace.h
linux-4.4.3/drivers/usb/storage/debug.h
linux-4.4.3/drivers/usb/storage/initializers.h
linux-4.4.3/drivers/usb/storage/initializers.c
linux-4.4.3/drivers/usb/storage/option_ms.h
linux-4.4.3/drivers/usb/storage/option_ms.c
linux-4.4.3/drivers/usb/storage/protocol.h
linux-4.4.3/drivers/usb/storage/protocol.c
linux-4.4.3/drivers/usb/storage/scsiglue.h
linux-4.4.3/drivers/usb/storage/scsiglue.c
linux-4.4.3/drivers/usb/storage/sierra_ms.h
linux-4.4.3/drivers/usb/storage/sierra_ms.c
linux-4.4.3/drivers/usb/storage/transport.h
linux-4.4.3/drivers/usb/storage/transport.c
linux-4.4.3/drivers/usb/storage/unusual_alauda.h
linux-4.4.3/drivers/usb/storage/unusual_cypress.h
linux-4.4.3/drivers/usb/storage/unusual_datafab.h
linux-4.4.3/drivers/usb/storage/unusual_devs.h
linux-4.4.3/drivers/usb/storage/unusual_ene_ub6250.h
linux-4.4.3/drivers/usb/storage/unusual_freecom.h
linux-4.4.3/drivers/usb/storage/unusual_isd200.h
linux-4.4.3/drivers/usb/storage/unusual_jumpshot.h
linux-4.4.3/drivers/usb/storage/unusual_karma.h
linux-4.4.3/drivers/usb/storage/unusual_onetouch.h
linux-4.4.3/drivers/usb/storage/unusual_realtek.h
linux-4.4.3/drivers/usb/storage/unusual_sddr09.h
linux-4.4.3/drivers/usb/storage/unusual_sddr55.h
linux-4.4.3/drivers/usb/storage/unusual_usbat.h
linux-4.4.3/drivers/usb/storage/usb.h
linux-4.4.3/drivers/usb/storage/usb.c
linux-4.4.3/drivers/usb/storage/usual-tables.c
linux-4.4.3/include/asm-generic/bitops/__ffs.h
linux-4.4.3/include/asm-generic/bitops/__fls.h
linux-4.4.3/include/asm-generic/bitops/fls64.h
linux-4.4.3/include/asm-generic/bitops/non-atomic.h
linux-4.4.3/include/asm-generic/ioctl.h
linux-4.4.3/include/linux/hiddev.h
linux-4.4.3/include/linux/hid.h
linux-4.4.3/include/linux/input.h
linux-4.4.3/include/linux/input/mt.h
linux-4.4.3/include/linux/leds.h
linux-4.4.3/include/linux/list.h
linux-4.4.3/include/linux/log2.h
linux-4.4.3/include/linux/mod_devicetable.h
linux-4.4.3/include/linux/netdev_features.h
linux-4.4.3/include/linux/pci_ids.h
linux-4.4.3/include/linux/platform_data/usb-omap.h
linux-4.4.3/include/linux/power_supply.h
linux-4.4.3/include/linux/swab.h
linux-4.4.3/include/linux/usb.h
linux-4.4.3/include/linux/usb_usual.h
linux-4.4.3/include/linux/usb/ch9.h
linux-4.4.3/include/linux/usb/cdc.h
linux-4.4.3/include/linux/usb/ehci-dbgp.h
linux-4.4.3/include/linux/usb/ehci_def.h
linux-4.4.3/include/linux/usb/hcd.h
linux-4.4.3/include/linux/usb/input.h
linux-4.4.3/include/linux/io-64-nonatomic-lo-hi.h
linux-4.4.3/include/linux/usb/otg.h
linux-4.4.3/include/linux/usb/phy.h
linux-4.4.3/include/linux/usb/quirks.h
linux-4.4.3/include/linux/usb/storage.h
linux-4.4.3/include/linux/usb/usbnet.h
linux-4.4.3/include/scsi/scsi.h
linux-4.4.3/include/scsi/scsi_host.h
linux-4.4.3/include/scsi/scsi_proto.h
linux-4.4.3/include/uapi/asm-generic/ioctl.h
linux-4.4.3/include/uapi/linux/byteorder/little_endian.h
linux-4.4.3/include/uapi/linux/hid.h
linux-4.4.3/include/uapi/linux/input.h
linux-4.4.3/include/uapi/linux/input-event-codes.h
linux-4.4.3/include/uapi/linux/pci_regs.h
linux-4.4.3/include/uapi/linux/stat.h
linux-4.4.3/include/uapi/linux/swab.h
linux-4.4.3/include/uapi/linux/usb/ch11.h
linux-4.4.3/include/uapi/linux/usb/ch9.h
linux-4.4.3/include/uapi/linux/usb/cdc.h
linux-4.4.3/lib/int_sqrt.c