Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
82442723
Commit
82442723
authored
Nov 30, 2010
by
Greg Kroah-Hartman
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-usb-linus' of
git://git.kernel.org/pub/scm/linux/kernel/git/sarah/xhci
into work
parents
abf03184
6dd0a3a7
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
215 additions
and
0 deletions
+215
-0
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-hub.c
+7
-0
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-mem.c
+164
-0
drivers/usb/host/xhci.c
drivers/usb/host/xhci.c
+18
-0
drivers/usb/host/xhci.h
drivers/usb/host/xhci.h
+26
-0
No files found.
drivers/usb/host/xhci-hub.c
View file @
82442723
...
...
@@ -229,6 +229,13 @@ void xhci_ring_device(struct xhci_hcd *xhci, int slot_id)
static
void
xhci_disable_port
(
struct
xhci_hcd
*
xhci
,
u16
wIndex
,
u32
__iomem
*
addr
,
u32
port_status
)
{
/* Don't allow the USB core to disable SuperSpeed ports. */
if
(
xhci
->
port_array
[
wIndex
]
==
0x03
)
{
xhci_dbg
(
xhci
,
"Ignoring request to disable "
"SuperSpeed port.
\n
"
);
return
;
}
/* Write 1 to disable the port */
xhci_writel
(
xhci
,
port_status
|
PORT_PE
,
addr
);
port_status
=
xhci_readl
(
xhci
,
addr
);
...
...
drivers/usb/host/xhci-mem.c
View file @
82442723
...
...
@@ -1443,6 +1443,13 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
xhci
->
dcbaa
=
NULL
;
scratchpad_free
(
xhci
);
xhci
->
num_usb2_ports
=
0
;
xhci
->
num_usb3_ports
=
0
;
kfree
(
xhci
->
usb2_ports
);
kfree
(
xhci
->
usb3_ports
);
kfree
(
xhci
->
port_array
);
xhci
->
page_size
=
0
;
xhci
->
page_shift
=
0
;
xhci
->
bus_suspended
=
0
;
...
...
@@ -1627,6 +1634,161 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
&
xhci
->
ir_set
->
erst_dequeue
);
}
static
void
xhci_add_in_port
(
struct
xhci_hcd
*
xhci
,
unsigned
int
num_ports
,
u32
__iomem
*
addr
,
u8
major_revision
)
{
u32
temp
,
port_offset
,
port_count
;
int
i
;
if
(
major_revision
>
0x03
)
{
xhci_warn
(
xhci
,
"Ignoring unknown port speed, "
"Ext Cap %p, revision = 0x%x
\n
"
,
addr
,
major_revision
);
/* Ignoring port protocol we can't understand. FIXME */
return
;
}
/* Port offset and count in the third dword, see section 7.2 */
temp
=
xhci_readl
(
xhci
,
addr
+
2
);
port_offset
=
XHCI_EXT_PORT_OFF
(
temp
);
port_count
=
XHCI_EXT_PORT_COUNT
(
temp
);
xhci_dbg
(
xhci
,
"Ext Cap %p, port offset = %u, "
"count = %u, revision = 0x%x
\n
"
,
addr
,
port_offset
,
port_count
,
major_revision
);
/* Port count includes the current port offset */
if
(
port_offset
==
0
||
(
port_offset
+
port_count
-
1
)
>
num_ports
)
/* WTF? "Valid values are ‘1’ to MaxPorts" */
return
;
port_offset
--
;
for
(
i
=
port_offset
;
i
<
(
port_offset
+
port_count
);
i
++
)
{
/* Duplicate entry. Ignore the port if the revisions differ. */
if
(
xhci
->
port_array
[
i
]
!=
0
)
{
xhci_warn
(
xhci
,
"Duplicate port entry, Ext Cap %p,"
" port %u
\n
"
,
addr
,
i
);
xhci_warn
(
xhci
,
"Port was marked as USB %u, "
"duplicated as USB %u
\n
"
,
xhci
->
port_array
[
i
],
major_revision
);
/* Only adjust the roothub port counts if we haven't
* found a similar duplicate.
*/
if
(
xhci
->
port_array
[
i
]
!=
major_revision
&&
xhci
->
port_array
[
i
]
!=
(
u8
)
-
1
)
{
if
(
xhci
->
port_array
[
i
]
==
0x03
)
xhci
->
num_usb3_ports
--
;
else
xhci
->
num_usb2_ports
--
;
xhci
->
port_array
[
i
]
=
(
u8
)
-
1
;
}
/* FIXME: Should we disable the port? */
}
xhci
->
port_array
[
i
]
=
major_revision
;
if
(
major_revision
==
0x03
)
xhci
->
num_usb3_ports
++
;
else
xhci
->
num_usb2_ports
++
;
}
/* FIXME: Should we disable ports not in the Extended Capabilities? */
}
/*
* Scan the Extended Capabilities for the "Supported Protocol Capabilities" that
* specify what speeds each port is supposed to be. We can't count on the port
* speed bits in the PORTSC register being correct until a device is connected,
* but we need to set up the two fake roothubs with the correct number of USB
* 3.0 and USB 2.0 ports at host controller initialization time.
*/
static
int
xhci_setup_port_arrays
(
struct
xhci_hcd
*
xhci
,
gfp_t
flags
)
{
u32
__iomem
*
addr
;
u32
offset
;
unsigned
int
num_ports
;
int
i
,
port_index
;
addr
=
&
xhci
->
cap_regs
->
hcc_params
;
offset
=
XHCI_HCC_EXT_CAPS
(
xhci_readl
(
xhci
,
addr
));
if
(
offset
==
0
)
{
xhci_err
(
xhci
,
"No Extended Capability registers, "
"unable to set up roothub.
\n
"
);
return
-
ENODEV
;
}
num_ports
=
HCS_MAX_PORTS
(
xhci
->
hcs_params1
);
xhci
->
port_array
=
kzalloc
(
sizeof
(
*
xhci
->
port_array
)
*
num_ports
,
flags
);
if
(
!
xhci
->
port_array
)
return
-
ENOMEM
;
/*
* For whatever reason, the first capability offset is from the
* capability register base, not from the HCCPARAMS register.
* See section 5.3.6 for offset calculation.
*/
addr
=
&
xhci
->
cap_regs
->
hc_capbase
+
offset
;
while
(
1
)
{
u32
cap_id
;
cap_id
=
xhci_readl
(
xhci
,
addr
);
if
(
XHCI_EXT_CAPS_ID
(
cap_id
)
==
XHCI_EXT_CAPS_PROTOCOL
)
xhci_add_in_port
(
xhci
,
num_ports
,
addr
,
(
u8
)
XHCI_EXT_PORT_MAJOR
(
cap_id
));
offset
=
XHCI_EXT_CAPS_NEXT
(
cap_id
);
if
(
!
offset
||
(
xhci
->
num_usb2_ports
+
xhci
->
num_usb3_ports
)
==
num_ports
)
break
;
/*
* Once you're into the Extended Capabilities, the offset is
* always relative to the register holding the offset.
*/
addr
+=
offset
;
}
if
(
xhci
->
num_usb2_ports
==
0
&&
xhci
->
num_usb3_ports
==
0
)
{
xhci_warn
(
xhci
,
"No ports on the roothubs?
\n
"
);
return
-
ENODEV
;
}
xhci_dbg
(
xhci
,
"Found %u USB 2.0 ports and %u USB 3.0 ports.
\n
"
,
xhci
->
num_usb2_ports
,
xhci
->
num_usb3_ports
);
/*
* Note we could have all USB 3.0 ports, or all USB 2.0 ports.
* Not sure how the USB core will handle a hub with no ports...
*/
if
(
xhci
->
num_usb2_ports
)
{
xhci
->
usb2_ports
=
kmalloc
(
sizeof
(
*
xhci
->
usb2_ports
)
*
xhci
->
num_usb2_ports
,
flags
);
if
(
!
xhci
->
usb2_ports
)
return
-
ENOMEM
;
port_index
=
0
;
for
(
i
=
0
;
i
<
num_ports
;
i
++
)
if
(
xhci
->
port_array
[
i
]
!=
0x03
)
{
xhci
->
usb2_ports
[
port_index
]
=
&
xhci
->
op_regs
->
port_status_base
+
NUM_PORT_REGS
*
i
;
xhci_dbg
(
xhci
,
"USB 2.0 port at index %u, "
"addr = %p
\n
"
,
i
,
xhci
->
usb2_ports
[
port_index
]);
port_index
++
;
}
}
if
(
xhci
->
num_usb3_ports
)
{
xhci
->
usb3_ports
=
kmalloc
(
sizeof
(
*
xhci
->
usb3_ports
)
*
xhci
->
num_usb3_ports
,
flags
);
if
(
!
xhci
->
usb3_ports
)
return
-
ENOMEM
;
port_index
=
0
;
for
(
i
=
0
;
i
<
num_ports
;
i
++
)
if
(
xhci
->
port_array
[
i
]
==
0x03
)
{
xhci
->
usb3_ports
[
port_index
]
=
&
xhci
->
op_regs
->
port_status_base
+
NUM_PORT_REGS
*
i
;
xhci_dbg
(
xhci
,
"USB 3.0 port at index %u, "
"addr = %p
\n
"
,
i
,
xhci
->
usb3_ports
[
port_index
]);
port_index
++
;
}
}
return
0
;
}
int
xhci_mem_init
(
struct
xhci_hcd
*
xhci
,
gfp_t
flags
)
{
...
...
@@ -1809,6 +1971,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
if
(
scratchpad_alloc
(
xhci
,
flags
))
goto
fail
;
if
(
xhci_setup_port_arrays
(
xhci
,
flags
))
goto
fail
;
return
0
;
...
...
drivers/usb/host/xhci.c
View file @
82442723
...
...
@@ -1549,6 +1549,15 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
cmd_completion
=
command
->
completion
;
cmd_status
=
&
command
->
status
;
command
->
command_trb
=
xhci
->
cmd_ring
->
enqueue
;
/* Enqueue pointer can be left pointing to the link TRB,
* we must handle that
*/
if
((
command
->
command_trb
->
link
.
control
&
TRB_TYPE_BITMASK
)
==
TRB_TYPE
(
TRB_LINK
))
command
->
command_trb
=
xhci
->
cmd_ring
->
enq_seg
->
next
->
trbs
;
list_add_tail
(
&
command
->
cmd_list
,
&
virt_dev
->
cmd_list
);
}
else
{
in_ctx
=
virt_dev
->
in_ctx
;
...
...
@@ -2272,6 +2281,15 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
/* Attempt to submit the Reset Device command to the command ring */
spin_lock_irqsave
(
&
xhci
->
lock
,
flags
);
reset_device_cmd
->
command_trb
=
xhci
->
cmd_ring
->
enqueue
;
/* Enqueue pointer can be left pointing to the link TRB,
* we must handle that
*/
if
((
reset_device_cmd
->
command_trb
->
link
.
control
&
TRB_TYPE_BITMASK
)
==
TRB_TYPE
(
TRB_LINK
))
reset_device_cmd
->
command_trb
=
xhci
->
cmd_ring
->
enq_seg
->
next
->
trbs
;
list_add_tail
(
&
reset_device_cmd
->
cmd_list
,
&
virt_dev
->
cmd_list
);
ret
=
xhci_queue_reset_device
(
xhci
,
slot_id
);
if
(
ret
)
{
...
...
drivers/usb/host/xhci.h
View file @
82442723
...
...
@@ -453,6 +453,24 @@ struct xhci_doorbell_array {
#define STREAM_ID_TO_DB(p) (((p) & 0xffff) << 16)
/**
* struct xhci_protocol_caps
* @revision: major revision, minor revision, capability ID,
* and next capability pointer.
* @name_string: Four ASCII characters to say which spec this xHC
* follows, typically "USB ".
* @port_info: Port offset, count, and protocol-defined information.
*/
struct
xhci_protocol_caps
{
u32
revision
;
u32
name_string
;
u32
port_info
;
};
#define XHCI_EXT_PORT_MAJOR(x) (((x) >> 24) & 0xff)
#define XHCI_EXT_PORT_OFF(x) ((x) & 0xff)
#define XHCI_EXT_PORT_COUNT(x) (((x) >> 8) & 0xff)
/**
* struct xhci_container_ctx
* @type: Type of context. Used to calculated offsets to contained contexts.
...
...
@@ -1240,6 +1258,14 @@ struct xhci_hcd {
u32
suspended_ports
[
8
];
/* which ports are
suspended */
unsigned
long
resume_done
[
MAX_HC_PORTS
];
/* Is each xHCI roothub port a USB 3.0, USB 2.0, or USB 1.1 port? */
u8
*
port_array
;
/* Array of pointers to USB 3.0 PORTSC registers */
u32
__iomem
**
usb3_ports
;
unsigned
int
num_usb3_ports
;
/* Array of pointers to USB 2.0 PORTSC registers */
u32
__iomem
**
usb2_ports
;
unsigned
int
num_usb2_ports
;
};
/* For testing purposes */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment