cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ehci-mem.c (5783B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * Copyright (c) 2001 by David Brownell
      4 */
      5
      6/* this file is part of ehci-hcd.c */
      7
      8/*-------------------------------------------------------------------------*/
      9
     10/*
     11 * There's basically three types of memory:
     12 *	- data used only by the HCD ... kmalloc is fine
     13 *	- async and periodic schedules, shared by HC and HCD ... these
     14 *	  need to use dma_pool or dma_alloc_coherent
     15 *	- driver buffers, read/written by HC ... single shot DMA mapped
     16 *
     17 * There's also "register" data (e.g. PCI or SOC), which is memory mapped.
     18 * No memory seen by this driver is pageable.
     19 */
     20
     21/*-------------------------------------------------------------------------*/
     22
     23/* Allocate the key transfer structures from the previously allocated pool */
     24
     25static inline void ehci_qtd_init(struct ehci_hcd *ehci, struct ehci_qtd *qtd,
     26				  dma_addr_t dma)
     27{
     28	memset (qtd, 0, sizeof *qtd);
     29	qtd->qtd_dma = dma;
     30	qtd->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT);
     31	qtd->hw_next = EHCI_LIST_END(ehci);
     32	qtd->hw_alt_next = EHCI_LIST_END(ehci);
     33	INIT_LIST_HEAD (&qtd->qtd_list);
     34}
     35
     36static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, gfp_t flags)
     37{
     38	struct ehci_qtd		*qtd;
     39	dma_addr_t		dma;
     40
     41	qtd = dma_pool_alloc (ehci->qtd_pool, flags, &dma);
     42	if (qtd != NULL) {
     43		ehci_qtd_init(ehci, qtd, dma);
     44	}
     45	return qtd;
     46}
     47
     48static inline void ehci_qtd_free (struct ehci_hcd *ehci, struct ehci_qtd *qtd)
     49{
     50	dma_pool_free (ehci->qtd_pool, qtd, qtd->qtd_dma);
     51}
     52
     53
     54static void qh_destroy(struct ehci_hcd *ehci, struct ehci_qh *qh)
     55{
     56	/* clean qtds first, and know this is not linked */
     57	if (!list_empty (&qh->qtd_list) || qh->qh_next.ptr) {
     58		ehci_dbg (ehci, "unused qh not empty!\n");
     59		BUG ();
     60	}
     61	if (qh->dummy)
     62		ehci_qtd_free (ehci, qh->dummy);
     63	dma_pool_free(ehci->qh_pool, qh->hw, qh->qh_dma);
     64	kfree(qh);
     65}
     66
     67static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags)
     68{
     69	struct ehci_qh		*qh;
     70	dma_addr_t		dma;
     71
     72	qh = kzalloc(sizeof *qh, GFP_ATOMIC);
     73	if (!qh)
     74		goto done;
     75	qh->hw = (struct ehci_qh_hw *)
     76		dma_pool_zalloc(ehci->qh_pool, flags, &dma);
     77	if (!qh->hw)
     78		goto fail;
     79	qh->qh_dma = dma;
     80	// INIT_LIST_HEAD (&qh->qh_list);
     81	INIT_LIST_HEAD (&qh->qtd_list);
     82	INIT_LIST_HEAD(&qh->unlink_node);
     83
     84	/* dummy td enables safe urb queuing */
     85	qh->dummy = ehci_qtd_alloc (ehci, flags);
     86	if (qh->dummy == NULL) {
     87		ehci_dbg (ehci, "no dummy td\n");
     88		goto fail1;
     89	}
     90done:
     91	return qh;
     92fail1:
     93	dma_pool_free(ehci->qh_pool, qh->hw, qh->qh_dma);
     94fail:
     95	kfree(qh);
     96	return NULL;
     97}
     98
     99/*-------------------------------------------------------------------------*/
    100
    101/* The queue heads and transfer descriptors are managed from pools tied
    102 * to each of the "per device" structures.
    103 * This is the initialisation and cleanup code.
    104 */
    105
    106static void ehci_mem_cleanup (struct ehci_hcd *ehci)
    107{
    108	if (ehci->async)
    109		qh_destroy(ehci, ehci->async);
    110	ehci->async = NULL;
    111
    112	if (ehci->dummy)
    113		qh_destroy(ehci, ehci->dummy);
    114	ehci->dummy = NULL;
    115
    116	/* DMA consistent memory and pools */
    117	dma_pool_destroy(ehci->qtd_pool);
    118	ehci->qtd_pool = NULL;
    119	dma_pool_destroy(ehci->qh_pool);
    120	ehci->qh_pool = NULL;
    121	dma_pool_destroy(ehci->itd_pool);
    122	ehci->itd_pool = NULL;
    123	dma_pool_destroy(ehci->sitd_pool);
    124	ehci->sitd_pool = NULL;
    125
    126	if (ehci->periodic)
    127		dma_free_coherent(ehci_to_hcd(ehci)->self.sysdev,
    128			ehci->periodic_size * sizeof (u32),
    129			ehci->periodic, ehci->periodic_dma);
    130	ehci->periodic = NULL;
    131
    132	/* shadow periodic table */
    133	kfree(ehci->pshadow);
    134	ehci->pshadow = NULL;
    135}
    136
    137/* remember to add cleanup code (above) if you add anything here */
    138static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
    139{
    140	int i;
    141
    142	/* QTDs for control/bulk/intr transfers */
    143	ehci->qtd_pool = dma_pool_create ("ehci_qtd",
    144			ehci_to_hcd(ehci)->self.sysdev,
    145			sizeof (struct ehci_qtd),
    146			32 /* byte alignment (for hw parts) */,
    147			4096 /* can't cross 4K */);
    148	if (!ehci->qtd_pool) {
    149		goto fail;
    150	}
    151
    152	/* QHs for control/bulk/intr transfers */
    153	ehci->qh_pool = dma_pool_create ("ehci_qh",
    154			ehci_to_hcd(ehci)->self.sysdev,
    155			sizeof(struct ehci_qh_hw),
    156			32 /* byte alignment (for hw parts) */,
    157			4096 /* can't cross 4K */);
    158	if (!ehci->qh_pool) {
    159		goto fail;
    160	}
    161	ehci->async = ehci_qh_alloc (ehci, flags);
    162	if (!ehci->async) {
    163		goto fail;
    164	}
    165
    166	/* ITD for high speed ISO transfers */
    167	ehci->itd_pool = dma_pool_create ("ehci_itd",
    168			ehci_to_hcd(ehci)->self.sysdev,
    169			sizeof (struct ehci_itd),
    170			32 /* byte alignment (for hw parts) */,
    171			4096 /* can't cross 4K */);
    172	if (!ehci->itd_pool) {
    173		goto fail;
    174	}
    175
    176	/* SITD for full/low speed split ISO transfers */
    177	ehci->sitd_pool = dma_pool_create ("ehci_sitd",
    178			ehci_to_hcd(ehci)->self.sysdev,
    179			sizeof (struct ehci_sitd),
    180			32 /* byte alignment (for hw parts) */,
    181			4096 /* can't cross 4K */);
    182	if (!ehci->sitd_pool) {
    183		goto fail;
    184	}
    185
    186	/* Hardware periodic table */
    187	ehci->periodic = (__le32 *)
    188		dma_alloc_coherent(ehci_to_hcd(ehci)->self.sysdev,
    189			ehci->periodic_size * sizeof(__le32),
    190			&ehci->periodic_dma, flags);
    191	if (ehci->periodic == NULL) {
    192		goto fail;
    193	}
    194
    195	if (ehci->use_dummy_qh) {
    196		struct ehci_qh_hw	*hw;
    197		ehci->dummy = ehci_qh_alloc(ehci, flags);
    198		if (!ehci->dummy)
    199			goto fail;
    200
    201		hw = ehci->dummy->hw;
    202		hw->hw_next = EHCI_LIST_END(ehci);
    203		hw->hw_qtd_next = EHCI_LIST_END(ehci);
    204		hw->hw_alt_next = EHCI_LIST_END(ehci);
    205		ehci->dummy->hw = hw;
    206
    207		for (i = 0; i < ehci->periodic_size; i++)
    208			ehci->periodic[i] = cpu_to_hc32(ehci,
    209					ehci->dummy->qh_dma);
    210	} else {
    211		for (i = 0; i < ehci->periodic_size; i++)
    212			ehci->periodic[i] = EHCI_LIST_END(ehci);
    213	}
    214
    215	/* software shadow of hardware table */
    216	ehci->pshadow = kcalloc(ehci->periodic_size, sizeof(void *), flags);
    217	if (ehci->pshadow != NULL)
    218		return 0;
    219
    220fail:
    221	ehci_dbg (ehci, "couldn't init memory\n");
    222	ehci_mem_cleanup (ehci);
    223	return -ENOMEM;
    224}