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

ohci-mem.c (4126B)


      1// SPDX-License-Identifier: GPL-1.0+
      2/*
      3 * OHCI HCD (Host Controller Driver) for USB.
      4 *
      5 * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
      6 * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
      7 *
      8 * This file is licenced under the GPL.
      9 */
     10
     11/*-------------------------------------------------------------------------*/
     12
     13/*
     14 * OHCI deals with three types of memory:
     15 *	- data used only by the HCD ... kmalloc is fine
     16 *	- async and periodic schedules, shared by HC and HCD ... these
     17 *	  need to use dma_pool or dma_alloc_coherent
     18 *	- driver buffers, read/written by HC ... the hcd glue or the
     19 *	  device driver provides us with dma addresses
     20 *
     21 * There's also "register" data, which is memory mapped.
     22 * No memory seen by this driver (or any HCD) may be paged out.
     23 */
     24
     25/*-------------------------------------------------------------------------*/
     26
     27static void ohci_hcd_init (struct ohci_hcd *ohci)
     28{
     29	ohci->next_statechange = jiffies;
     30	spin_lock_init (&ohci->lock);
     31	INIT_LIST_HEAD (&ohci->pending);
     32	INIT_LIST_HEAD(&ohci->eds_in_use);
     33}
     34
     35/*-------------------------------------------------------------------------*/
     36
     37static int ohci_mem_init (struct ohci_hcd *ohci)
     38{
     39	/*
     40	 * HCs with local memory allocate from localmem_pool so there's
     41	 * no need to create the below dma pools.
     42	 */
     43	if (ohci_to_hcd(ohci)->localmem_pool)
     44		return 0;
     45
     46	ohci->td_cache = dma_pool_create ("ohci_td",
     47		ohci_to_hcd(ohci)->self.controller,
     48		sizeof (struct td),
     49		32 /* byte alignment */,
     50		0 /* no page-crossing issues */);
     51	if (!ohci->td_cache)
     52		return -ENOMEM;
     53	ohci->ed_cache = dma_pool_create ("ohci_ed",
     54		ohci_to_hcd(ohci)->self.controller,
     55		sizeof (struct ed),
     56		16 /* byte alignment */,
     57		0 /* no page-crossing issues */);
     58	if (!ohci->ed_cache) {
     59		dma_pool_destroy (ohci->td_cache);
     60		return -ENOMEM;
     61	}
     62	return 0;
     63}
     64
     65static void ohci_mem_cleanup (struct ohci_hcd *ohci)
     66{
     67	dma_pool_destroy(ohci->td_cache);
     68	ohci->td_cache = NULL;
     69	dma_pool_destroy(ohci->ed_cache);
     70	ohci->ed_cache = NULL;
     71}
     72
     73/*-------------------------------------------------------------------------*/
     74
     75/* ohci "done list" processing needs this mapping */
     76static inline struct td *
     77dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma)
     78{
     79	struct td *td;
     80
     81	td_dma &= TD_MASK;
     82	td = hc->td_hash [TD_HASH_FUNC(td_dma)];
     83	while (td && td->td_dma != td_dma)
     84		td = td->td_hash;
     85	return td;
     86}
     87
     88/* TDs ... */
     89static struct td *
     90td_alloc (struct ohci_hcd *hc, gfp_t mem_flags)
     91{
     92	dma_addr_t	dma;
     93	struct td	*td;
     94	struct usb_hcd	*hcd = ohci_to_hcd(hc);
     95
     96	if (hcd->localmem_pool)
     97		td = gen_pool_dma_zalloc_align(hcd->localmem_pool,
     98				sizeof(*td), &dma, 32);
     99	else
    100		td = dma_pool_zalloc(hc->td_cache, mem_flags, &dma);
    101	if (td) {
    102		/* in case hc fetches it, make it look dead */
    103		td->hwNextTD = cpu_to_hc32 (hc, dma);
    104		td->td_dma = dma;
    105		/* hashed in td_fill */
    106	}
    107	return td;
    108}
    109
    110static void
    111td_free (struct ohci_hcd *hc, struct td *td)
    112{
    113	struct td	**prev = &hc->td_hash [TD_HASH_FUNC (td->td_dma)];
    114	struct usb_hcd	*hcd = ohci_to_hcd(hc);
    115
    116	while (*prev && *prev != td)
    117		prev = &(*prev)->td_hash;
    118	if (*prev)
    119		*prev = td->td_hash;
    120	else if ((td->hwINFO & cpu_to_hc32(hc, TD_DONE)) != 0)
    121		ohci_dbg (hc, "no hash for td %p\n", td);
    122
    123	if (hcd->localmem_pool)
    124		gen_pool_free(hcd->localmem_pool, (unsigned long)td,
    125			      sizeof(*td));
    126	else
    127		dma_pool_free(hc->td_cache, td, td->td_dma);
    128}
    129
    130/*-------------------------------------------------------------------------*/
    131
    132/* EDs ... */
    133static struct ed *
    134ed_alloc (struct ohci_hcd *hc, gfp_t mem_flags)
    135{
    136	dma_addr_t	dma;
    137	struct ed	*ed;
    138	struct usb_hcd	*hcd = ohci_to_hcd(hc);
    139
    140	if (hcd->localmem_pool)
    141		ed = gen_pool_dma_zalloc_align(hcd->localmem_pool,
    142				sizeof(*ed), &dma, 16);
    143	else
    144		ed = dma_pool_zalloc(hc->ed_cache, mem_flags, &dma);
    145	if (ed) {
    146		INIT_LIST_HEAD (&ed->td_list);
    147		ed->dma = dma;
    148	}
    149	return ed;
    150}
    151
    152static void
    153ed_free (struct ohci_hcd *hc, struct ed *ed)
    154{
    155	struct usb_hcd	*hcd = ohci_to_hcd(hc);
    156
    157	if (hcd->localmem_pool)
    158		gen_pool_free(hcd->localmem_pool, (unsigned long)ed,
    159			      sizeof(*ed));
    160	else
    161		dma_pool_free(hc->ed_cache, ed, ed->dma);
    162}
    163