mirror of
https://github.com/torvalds/linux.git
synced 2026-06-10 15:42:19 +02:00
Merge branch 'linux-tegra-2.6.36' into android-tegra-2.6.36
This commit is contained in:
commit
5a7997f3fb
|
|
@ -445,6 +445,7 @@ static int tegra_idle_enter_lp2(struct cpuidle_device *dev,
|
|||
return tegra_idle_enter_lp3(dev, state);
|
||||
|
||||
local_irq_disable();
|
||||
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
|
||||
local_fiq_disable();
|
||||
enter = ktime_get();
|
||||
|
||||
|
|
@ -463,11 +464,9 @@ static int tegra_idle_enter_lp2(struct cpuidle_device *dev,
|
|||
us = ktime_to_us(exit);
|
||||
|
||||
local_fiq_enable();
|
||||
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
|
||||
local_irq_enable();
|
||||
|
||||
/* cpu clockevents may have been reset by powerdown */
|
||||
hrtimer_peek_ahead_timers();
|
||||
|
||||
smp_rmb();
|
||||
state->exit_latency = tegra_lp2_exit_latency;
|
||||
state->target_residency = tegra_lp2_exit_latency +
|
||||
|
|
|
|||
|
|
@ -1264,6 +1264,14 @@ static void hcd_free_coherent(struct usb_bus *bus, dma_addr_t *dma_handle,
|
|||
}
|
||||
|
||||
static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
|
||||
{
|
||||
if (hcd->driver->unmap_urb_for_dma)
|
||||
hcd->driver->unmap_urb_for_dma(hcd, urb);
|
||||
else
|
||||
usb_hcd_unmap_urb_for_dma(hcd, urb);
|
||||
}
|
||||
|
||||
void usb_hcd_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
|
||||
{
|
||||
enum dma_data_direction dir;
|
||||
|
||||
|
|
@ -1307,9 +1315,19 @@ static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
|
|||
URB_DMA_MAP_SG | URB_DMA_MAP_PAGE |
|
||||
URB_DMA_MAP_SINGLE | URB_MAP_LOCAL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_hcd_unmap_urb_for_dma);
|
||||
|
||||
static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
|
||||
gfp_t mem_flags)
|
||||
{
|
||||
if (hcd->driver->map_urb_for_dma)
|
||||
return hcd->driver->map_urb_for_dma(hcd, urb, mem_flags);
|
||||
else
|
||||
return usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
|
||||
}
|
||||
|
||||
int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
|
||||
gfp_t mem_flags)
|
||||
{
|
||||
enum dma_data_direction dir;
|
||||
int ret = 0;
|
||||
|
|
@ -1400,10 +1418,11 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
|
|||
}
|
||||
if (ret && (urb->transfer_flags & (URB_SETUP_MAP_SINGLE |
|
||||
URB_SETUP_MAP_LOCAL)))
|
||||
unmap_urb_for_dma(hcd, urb);
|
||||
usb_hcd_unmap_urb_for_dma(hcd, urb);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_hcd_map_urb_for_dma);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@
|
|||
#define TEGRA_USB_USBMODE_HOST (3 << 0)
|
||||
#define TEGRA_USB_PORTSC1_PTC(x) (((x) & 0xf) << 16)
|
||||
|
||||
#define TEGRA_USB_DMA_ALIGN 32
|
||||
|
||||
struct tegra_ehci_context {
|
||||
bool valid;
|
||||
u32 command;
|
||||
|
|
@ -468,6 +470,92 @@ static int tegra_ehci_bus_resume(struct usb_hcd *hcd)
|
|||
}
|
||||
#endif
|
||||
|
||||
struct temp_buffer {
|
||||
void *kmalloc_ptr;
|
||||
void *old_xfer_buffer;
|
||||
u8 data[0];
|
||||
};
|
||||
|
||||
static void free_temp_buffer(struct urb *urb)
|
||||
{
|
||||
enum dma_data_direction dir;
|
||||
struct temp_buffer *temp;
|
||||
|
||||
if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER))
|
||||
return;
|
||||
|
||||
dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
|
||||
|
||||
temp = container_of(urb->transfer_buffer, struct temp_buffer,
|
||||
data);
|
||||
|
||||
if (dir == DMA_FROM_DEVICE)
|
||||
memcpy(temp->old_xfer_buffer, temp->data,
|
||||
urb->transfer_buffer_length);
|
||||
urb->transfer_buffer = temp->old_xfer_buffer;
|
||||
kfree(temp->kmalloc_ptr);
|
||||
|
||||
urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER;
|
||||
}
|
||||
|
||||
static int alloc_temp_buffer(struct urb *urb, gfp_t mem_flags)
|
||||
{
|
||||
enum dma_data_direction dir;
|
||||
struct temp_buffer *temp, *kmalloc_ptr;
|
||||
size_t kmalloc_size;
|
||||
|
||||
if (urb->num_sgs || urb->sg ||
|
||||
urb->transfer_buffer_length == 0 ||
|
||||
!((uintptr_t)urb->transfer_buffer & (TEGRA_USB_DMA_ALIGN - 1)))
|
||||
return 0;
|
||||
|
||||
dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
|
||||
|
||||
/* Allocate a buffer with enough padding for alignment */
|
||||
kmalloc_size = urb->transfer_buffer_length +
|
||||
sizeof(struct temp_buffer) + TEGRA_USB_DMA_ALIGN - 1;
|
||||
|
||||
kmalloc_ptr = kmalloc(kmalloc_size, mem_flags);
|
||||
if (!kmalloc_ptr)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Position our struct temp_buffer such that data is aligned */
|
||||
temp = PTR_ALIGN(kmalloc_ptr + 1, TEGRA_USB_DMA_ALIGN) - 1;
|
||||
|
||||
temp->kmalloc_ptr = kmalloc_ptr;
|
||||
temp->old_xfer_buffer = urb->transfer_buffer;
|
||||
if (dir == DMA_TO_DEVICE)
|
||||
memcpy(temp->data, urb->transfer_buffer,
|
||||
urb->transfer_buffer_length);
|
||||
urb->transfer_buffer = temp->data;
|
||||
|
||||
urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_ehci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
|
||||
gfp_t mem_flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = alloc_temp_buffer(urb, mem_flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
|
||||
if (ret)
|
||||
free_temp_buffer(urb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
|
||||
{
|
||||
usb_hcd_unmap_urb_for_dma(hcd, urb);
|
||||
free_temp_buffer(urb);
|
||||
}
|
||||
|
||||
static const struct hc_driver tegra_ehci_hc_driver = {
|
||||
.description = hcd_name,
|
||||
.product_desc = "Tegra EHCI Host Controller",
|
||||
|
|
@ -483,6 +571,8 @@ static const struct hc_driver tegra_ehci_hc_driver = {
|
|||
.shutdown = tegra_ehci_shutdown,
|
||||
.urb_enqueue = ehci_urb_enqueue,
|
||||
.urb_dequeue = ehci_urb_dequeue,
|
||||
.map_urb_for_dma = tegra_ehci_map_urb_for_dma,
|
||||
.unmap_urb_for_dma = tegra_ehci_unmap_urb_for_dma,
|
||||
.endpoint_disable = ehci_endpoint_disable,
|
||||
.endpoint_reset = ehci_endpoint_reset,
|
||||
.get_frame_number = ehci_get_frame,
|
||||
|
|
|
|||
|
|
@ -262,7 +262,6 @@ struct _mmc_csd {
|
|||
#define EXT_CSD_S_A_TIMEOUT 217 /* RO */
|
||||
#define EXT_CSD_ERASE_TIMEOUT_MULT 223 /* RO */
|
||||
#define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */
|
||||
#define EXT_CSD_BOOT_SIZE_MULTI 226
|
||||
#define EXT_CSD_SEC_TRIM_MULT 229 /* RO */
|
||||
#define EXT_CSD_SEC_ERASE_MULT 230 /* RO */
|
||||
#define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */
|
||||
|
|
|
|||
|
|
@ -975,6 +975,7 @@ extern int usb_disabled(void);
|
|||
#define URB_SETUP_MAP_SINGLE 0x00100000 /* Setup packet DMA mapped */
|
||||
#define URB_SETUP_MAP_LOCAL 0x00200000 /* HCD-local setup packet */
|
||||
#define URB_DMA_SG_COMBINED 0x00400000 /* S-G entries were combined */
|
||||
#define URB_ALIGNED_TEMP_BUFFER 0x00800000 /* Temp buffer was alloc'd */
|
||||
|
||||
struct usb_iso_packet_descriptor {
|
||||
unsigned int offset;
|
||||
|
|
|
|||
|
|
@ -233,6 +233,19 @@ struct hc_driver {
|
|||
int (*urb_dequeue)(struct usb_hcd *hcd,
|
||||
struct urb *urb, int status);
|
||||
|
||||
/*
|
||||
* (optional) these hooks allow an HCD to override the default DMA
|
||||
* mapping and unmapping routines. In general, they shouldn't be
|
||||
* necessary unless the host controller has special DMA requirements,
|
||||
* such as alignment contraints. If these are not specified, the
|
||||
* general usb_hcd_(un)?map_urb_for_dma functions will be used instead
|
||||
* (and it may be a good idea to call these functions in your HCD
|
||||
* implementation)
|
||||
*/
|
||||
int (*map_urb_for_dma)(struct usb_hcd *hcd, struct urb *urb,
|
||||
gfp_t mem_flags);
|
||||
void (*unmap_urb_for_dma)(struct usb_hcd *hcd, struct urb *urb);
|
||||
|
||||
/* hw synch, freeing endpoint resources that urb_dequeue can't */
|
||||
void (*endpoint_disable)(struct usb_hcd *hcd,
|
||||
struct usb_host_endpoint *ep);
|
||||
|
|
@ -329,6 +342,9 @@ extern int usb_hcd_submit_urb(struct urb *urb, gfp_t mem_flags);
|
|||
extern int usb_hcd_unlink_urb(struct urb *urb, int status);
|
||||
extern void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb,
|
||||
int status);
|
||||
extern int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
|
||||
gfp_t mem_flags);
|
||||
extern void usb_hcd_unmap_urb_for_dma(struct usb_hcd *, struct urb *);
|
||||
extern void usb_hcd_flush_endpoint(struct usb_device *udev,
|
||||
struct usb_host_endpoint *ep);
|
||||
extern void usb_hcd_disable_endpoint(struct usb_device *udev,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user