ehci: Fix memory coherence
This is a no-op on x86 but necessarry on ARM and may be necessarry on MIPS.
This commit is contained in:
parent
86ef66d977
commit
0f076d75d0
1 changed files with 41 additions and 0 deletions
|
@ -29,6 +29,7 @@
|
||||||
#include <grub/loader.h>
|
#include <grub/loader.h>
|
||||||
#include <grub/cs5536.h>
|
#include <grub/cs5536.h>
|
||||||
#include <grub/disk.h>
|
#include <grub/disk.h>
|
||||||
|
#include <grub/cache.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -337,6 +338,21 @@ struct grub_ehci
|
||||||
|
|
||||||
static struct grub_ehci *ehci;
|
static struct grub_ehci *ehci;
|
||||||
|
|
||||||
|
static void
|
||||||
|
sync_all_caches (struct grub_ehci *e)
|
||||||
|
{
|
||||||
|
if (!e)
|
||||||
|
return;
|
||||||
|
if (e->td_virt)
|
||||||
|
grub_arch_sync_dma_caches (e->td_virt, sizeof (struct grub_ehci_td) *
|
||||||
|
GRUB_EHCI_N_TD);
|
||||||
|
if (e->qh_virt)
|
||||||
|
grub_arch_sync_dma_caches (e->qh_virt, sizeof (struct grub_ehci_qh) *
|
||||||
|
GRUB_EHCI_N_QH);
|
||||||
|
if (e->framelist_virt)
|
||||||
|
grub_arch_sync_dma_caches (e->framelist_virt, 4096);
|
||||||
|
}
|
||||||
|
|
||||||
/* EHCC registers access functions */
|
/* EHCC registers access functions */
|
||||||
static inline grub_uint32_t
|
static inline grub_uint32_t
|
||||||
grub_ehci_ehcc_read32 (struct grub_ehci *e, grub_uint32_t addr)
|
grub_ehci_ehcc_read32 (struct grub_ehci *e, grub_uint32_t addr)
|
||||||
|
@ -437,6 +453,8 @@ grub_ehci_reset (struct grub_ehci *e)
|
||||||
{
|
{
|
||||||
grub_uint64_t maxtime;
|
grub_uint64_t maxtime;
|
||||||
|
|
||||||
|
sync_all_caches (e);
|
||||||
|
|
||||||
grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
|
grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
|
||||||
GRUB_EHCI_CMD_HC_RESET
|
GRUB_EHCI_CMD_HC_RESET
|
||||||
| grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
|
| grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
|
||||||
|
@ -840,6 +858,8 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
|
||||||
e->next = ehci;
|
e->next = ehci;
|
||||||
ehci = e;
|
ehci = e;
|
||||||
|
|
||||||
|
sync_all_caches (e);
|
||||||
|
|
||||||
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: OK at all\n");
|
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: OK at all\n");
|
||||||
|
|
||||||
grub_dprintf ("ehci",
|
grub_dprintf ("ehci",
|
||||||
|
@ -1020,6 +1040,7 @@ grub_ehci_find_qh (struct grub_ehci *e, grub_usb_transfer_t transfer)
|
||||||
/* Found proper existing (and linked) QH, do setup of QH */
|
/* Found proper existing (and linked) QH, do setup of QH */
|
||||||
grub_dprintf ("ehci", "find_qh: found, QH=%p\n", qh_iter);
|
grub_dprintf ("ehci", "find_qh: found, QH=%p\n", qh_iter);
|
||||||
grub_ehci_setup_qh (qh_iter, transfer);
|
grub_ehci_setup_qh (qh_iter, transfer);
|
||||||
|
sync_all_caches (e);
|
||||||
return qh_iter;
|
return qh_iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1291,6 +1312,8 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev,
|
||||||
struct grub_ehci_transfer_controller_data *cdata;
|
struct grub_ehci_transfer_controller_data *cdata;
|
||||||
grub_uint32_t status;
|
grub_uint32_t status;
|
||||||
|
|
||||||
|
sync_all_caches (e);
|
||||||
|
|
||||||
/* Check if EHCI is running and AL is enabled */
|
/* Check if EHCI is running and AL is enabled */
|
||||||
status = grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS);
|
status = grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS);
|
||||||
if ((status & GRUB_EHCI_ST_HC_HALTED) != 0)
|
if ((status & GRUB_EHCI_ST_HC_HALTED) != 0)
|
||||||
|
@ -1399,6 +1422,8 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev,
|
||||||
* i.e. reset token */
|
* i.e. reset token */
|
||||||
cdata->qh_virt->td_overlay.token = grub_cpu_to_le32_compile_time (0);
|
cdata->qh_virt->td_overlay.token = grub_cpu_to_le32_compile_time (0);
|
||||||
|
|
||||||
|
sync_all_caches (e);
|
||||||
|
|
||||||
/* Finito */
|
/* Finito */
|
||||||
transfer->controller_data = cdata;
|
transfer->controller_data = cdata;
|
||||||
|
|
||||||
|
@ -1447,6 +1472,8 @@ grub_ehci_parse_notrun (grub_usb_controller_t dev,
|
||||||
grub_ehci_free_td (e, cdata->td_alt_virt);
|
grub_ehci_free_td (e, cdata->td_alt_virt);
|
||||||
grub_free (cdata);
|
grub_free (cdata);
|
||||||
|
|
||||||
|
sync_all_caches (e);
|
||||||
|
|
||||||
/* Additionally, do something with EHCI to make it running (what?) */
|
/* Additionally, do something with EHCI to make it running (what?) */
|
||||||
/* Try enable EHCI and AL */
|
/* Try enable EHCI and AL */
|
||||||
grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
|
grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
|
||||||
|
@ -1482,6 +1509,8 @@ grub_ehci_parse_halt (grub_usb_controller_t dev,
|
||||||
grub_ehci_free_td (e, cdata->td_alt_virt);
|
grub_ehci_free_td (e, cdata->td_alt_virt);
|
||||||
grub_free (cdata);
|
grub_free (cdata);
|
||||||
|
|
||||||
|
sync_all_caches (e);
|
||||||
|
|
||||||
/* Evaluation of error code - currently we don't have GRUB USB error
|
/* Evaluation of error code - currently we don't have GRUB USB error
|
||||||
* codes for some EHCI states, GRUB_USB_ERR_DATA is used for them.
|
* codes for some EHCI states, GRUB_USB_ERR_DATA is used for them.
|
||||||
* Order of evaluation is critical, specially bubble/stall. */
|
* Order of evaluation is critical, specially bubble/stall. */
|
||||||
|
@ -1515,6 +1544,8 @@ grub_ehci_parse_success (grub_usb_controller_t dev,
|
||||||
grub_ehci_free_td (e, cdata->td_alt_virt);
|
grub_ehci_free_td (e, cdata->td_alt_virt);
|
||||||
grub_free (cdata);
|
grub_free (cdata);
|
||||||
|
|
||||||
|
sync_all_caches (e);
|
||||||
|
|
||||||
return GRUB_USB_ERR_NONE;
|
return GRUB_USB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1528,6 +1559,8 @@ grub_ehci_check_transfer (grub_usb_controller_t dev,
|
||||||
transfer->controller_data;
|
transfer->controller_data;
|
||||||
grub_uint32_t token, token_ftd;
|
grub_uint32_t token, token_ftd;
|
||||||
|
|
||||||
|
sync_all_caches (e);
|
||||||
|
|
||||||
grub_dprintf ("ehci",
|
grub_dprintf ("ehci",
|
||||||
"check_transfer: EHCI STATUS=%08x, cdata=%p, qh=%p\n",
|
"check_transfer: EHCI STATUS=%08x, cdata=%p, qh=%p\n",
|
||||||
grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS),
|
grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS),
|
||||||
|
@ -1594,6 +1627,9 @@ grub_ehci_cancel_transfer (grub_usb_controller_t dev,
|
||||||
int i;
|
int i;
|
||||||
grub_uint64_t maxtime;
|
grub_uint64_t maxtime;
|
||||||
grub_uint32_t qh_phys;
|
grub_uint32_t qh_phys;
|
||||||
|
|
||||||
|
sync_all_caches (e);
|
||||||
|
|
||||||
grub_uint32_t interrupt =
|
grub_uint32_t interrupt =
|
||||||
cdata->qh_virt->ep_cap & GRUB_EHCI_SMASK_MASK;
|
cdata->qh_virt->ep_cap & GRUB_EHCI_SMASK_MASK;
|
||||||
|
|
||||||
|
@ -1613,6 +1649,7 @@ grub_ehci_cancel_transfer (grub_usb_controller_t dev,
|
||||||
grub_ehci_free_tds (e, cdata->td_first_virt, transfer, &actual);
|
grub_ehci_free_tds (e, cdata->td_first_virt, transfer, &actual);
|
||||||
grub_ehci_free_td (e, cdata->td_alt_virt);
|
grub_ehci_free_td (e, cdata->td_alt_virt);
|
||||||
grub_free (cdata);
|
grub_free (cdata);
|
||||||
|
sync_all_caches (e);
|
||||||
grub_dprintf ("ehci", "cancel_transfer: end - EHCI not running\n");
|
grub_dprintf ("ehci", "cancel_transfer: end - EHCI not running\n");
|
||||||
return GRUB_USB_ERR_NONE;
|
return GRUB_USB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
@ -1635,6 +1672,8 @@ grub_ehci_cancel_transfer (grub_usb_controller_t dev,
|
||||||
/* Unlink QH from AL */
|
/* Unlink QH from AL */
|
||||||
e->qh_virt[i].qh_hptr = cdata->qh_virt->qh_hptr;
|
e->qh_virt[i].qh_hptr = cdata->qh_virt->qh_hptr;
|
||||||
|
|
||||||
|
sync_all_caches (e);
|
||||||
|
|
||||||
/* If this is an interrupt transfer, we just wait for the periodic
|
/* If this is an interrupt transfer, we just wait for the periodic
|
||||||
* schedule to advance a few times and then assume that the EHCI
|
* schedule to advance a few times and then assume that the EHCI
|
||||||
* controller has read the updated QH. */
|
* controller has read the updated QH. */
|
||||||
|
@ -1689,6 +1728,8 @@ grub_ehci_cancel_transfer (grub_usb_controller_t dev,
|
||||||
|
|
||||||
grub_dprintf ("ehci", "cancel_transfer: end\n");
|
grub_dprintf ("ehci", "cancel_transfer: end\n");
|
||||||
|
|
||||||
|
sync_all_caches (e);
|
||||||
|
|
||||||
return GRUB_USB_ERR_NONE;
|
return GRUB_USB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue