LCOV - code coverage report
Current view: top level - drivers/usb/host - ehci-mem.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 107 0.0 %
Date: 2022-03-28 15:32:58 Functions: 0 4 0.0 %
Branches: 0 40 0.0 %

           Branch data     Line data    Source code
       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                 :            : 
      25                 :          0 : static inline void ehci_qtd_init(struct ehci_hcd *ehci, struct ehci_qtd *qtd,
      26                 :            :                                   dma_addr_t dma)
      27                 :            : {
      28                 :          0 :         memset (qtd, 0, sizeof *qtd);
      29                 :          0 :         qtd->qtd_dma = dma;
      30                 :          0 :         qtd->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT);
      31                 :          0 :         qtd->hw_next = EHCI_LIST_END(ehci);
      32                 :          0 :         qtd->hw_alt_next = EHCI_LIST_END(ehci);
      33                 :          0 :         INIT_LIST_HEAD (&qtd->qtd_list);
      34                 :            : }
      35                 :            : 
      36                 :            : static 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                 :            : 
      48                 :          0 : static inline void ehci_qtd_free (struct ehci_hcd *ehci, struct ehci_qtd *qtd)
      49                 :            : {
      50                 :          0 :         dma_pool_free (ehci->qtd_pool, qtd, qtd->qtd_dma);
      51                 :          0 : }
      52                 :            : 
      53                 :            : 
      54                 :          0 : static void qh_destroy(struct ehci_hcd *ehci, struct ehci_qh *qh)
      55                 :            : {
      56                 :            :         /* clean qtds first, and know this is not linked */
      57   [ #  #  #  # ]:          0 :         if (!list_empty (&qh->qtd_list) || qh->qh_next.ptr) {
      58                 :          0 :                 ehci_dbg (ehci, "unused qh not empty!\n");
      59                 :          0 :                 BUG ();
      60                 :            :         }
      61         [ #  # ]:          0 :         if (qh->dummy)
      62                 :          0 :                 ehci_qtd_free (ehci, qh->dummy);
      63                 :          0 :         dma_pool_free(ehci->qh_pool, qh->hw, qh->qh_dma);
      64                 :          0 :         kfree(qh);
      65                 :          0 : }
      66                 :            : 
      67                 :          0 : static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags)
      68                 :            : {
      69                 :          0 :         struct ehci_qh          *qh;
      70                 :          0 :         dma_addr_t              dma;
      71                 :            : 
      72                 :          0 :         qh = kzalloc(sizeof *qh, GFP_ATOMIC);
      73         [ #  # ]:          0 :         if (!qh)
      74                 :          0 :                 goto done;
      75                 :          0 :         qh->hw = (struct ehci_qh_hw *)
      76                 :          0 :                 dma_pool_alloc(ehci->qh_pool, flags, &dma);
      77         [ #  # ]:          0 :         if (!qh->hw)
      78                 :          0 :                 goto fail;
      79                 :          0 :         memset(qh->hw, 0, sizeof *qh->hw);
      80                 :          0 :         qh->qh_dma = dma;
      81                 :            :         // INIT_LIST_HEAD (&qh->qh_list);
      82                 :          0 :         INIT_LIST_HEAD (&qh->qtd_list);
      83                 :          0 :         INIT_LIST_HEAD(&qh->unlink_node);
      84                 :            : 
      85                 :            :         /* dummy td enables safe urb queuing */
      86                 :          0 :         qh->dummy = ehci_qtd_alloc (ehci, flags);
      87         [ #  # ]:          0 :         if (qh->dummy == NULL) {
      88                 :          0 :                 ehci_dbg (ehci, "no dummy td\n");
      89                 :          0 :                 goto fail1;
      90                 :            :         }
      91                 :          0 : done:
      92                 :            :         return qh;
      93                 :            : fail1:
      94                 :          0 :         dma_pool_free(ehci->qh_pool, qh->hw, qh->qh_dma);
      95                 :          0 : fail:
      96                 :          0 :         kfree(qh);
      97                 :          0 :         return NULL;
      98                 :            : }
      99                 :            : 
     100                 :            : /*-------------------------------------------------------------------------*/
     101                 :            : 
     102                 :            : /* The queue heads and transfer descriptors are managed from pools tied
     103                 :            :  * to each of the "per device" structures.
     104                 :            :  * This is the initialisation and cleanup code.
     105                 :            :  */
     106                 :            : 
     107                 :          0 : static void ehci_mem_cleanup (struct ehci_hcd *ehci)
     108                 :            : {
     109         [ #  # ]:          0 :         if (ehci->async)
     110                 :          0 :                 qh_destroy(ehci, ehci->async);
     111                 :          0 :         ehci->async = NULL;
     112                 :            : 
     113         [ #  # ]:          0 :         if (ehci->dummy)
     114                 :          0 :                 qh_destroy(ehci, ehci->dummy);
     115                 :          0 :         ehci->dummy = NULL;
     116                 :            : 
     117                 :            :         /* DMA consistent memory and pools */
     118                 :          0 :         dma_pool_destroy(ehci->qtd_pool);
     119                 :          0 :         ehci->qtd_pool = NULL;
     120                 :          0 :         dma_pool_destroy(ehci->qh_pool);
     121                 :          0 :         ehci->qh_pool = NULL;
     122                 :          0 :         dma_pool_destroy(ehci->itd_pool);
     123                 :          0 :         ehci->itd_pool = NULL;
     124                 :          0 :         dma_pool_destroy(ehci->sitd_pool);
     125                 :          0 :         ehci->sitd_pool = NULL;
     126                 :            : 
     127         [ #  # ]:          0 :         if (ehci->periodic)
     128                 :          0 :                 dma_free_coherent(ehci_to_hcd(ehci)->self.sysdev,
     129                 :          0 :                         ehci->periodic_size * sizeof (u32),
     130                 :            :                         ehci->periodic, ehci->periodic_dma);
     131                 :          0 :         ehci->periodic = NULL;
     132                 :            : 
     133                 :            :         /* shadow periodic table */
     134                 :          0 :         kfree(ehci->pshadow);
     135                 :          0 :         ehci->pshadow = NULL;
     136                 :          0 : }
     137                 :            : 
     138                 :            : /* remember to add cleanup code (above) if you add anything here */
     139                 :          0 : static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
     140                 :            : {
     141                 :          0 :         int i;
     142                 :            : 
     143                 :            :         /* QTDs for control/bulk/intr transfers */
     144                 :          0 :         ehci->qtd_pool = dma_pool_create ("ehci_qtd",
     145                 :            :                         ehci_to_hcd(ehci)->self.sysdev,
     146                 :            :                         sizeof (struct ehci_qtd),
     147                 :            :                         32 /* byte alignment (for hw parts) */,
     148                 :            :                         4096 /* can't cross 4K */);
     149         [ #  # ]:          0 :         if (!ehci->qtd_pool) {
     150                 :          0 :                 goto fail;
     151                 :            :         }
     152                 :            : 
     153                 :            :         /* QHs for control/bulk/intr transfers */
     154                 :          0 :         ehci->qh_pool = dma_pool_create ("ehci_qh",
     155                 :            :                         ehci_to_hcd(ehci)->self.sysdev,
     156                 :            :                         sizeof(struct ehci_qh_hw),
     157                 :            :                         32 /* byte alignment (for hw parts) */,
     158                 :            :                         4096 /* can't cross 4K */);
     159         [ #  # ]:          0 :         if (!ehci->qh_pool) {
     160                 :          0 :                 goto fail;
     161                 :            :         }
     162                 :          0 :         ehci->async = ehci_qh_alloc (ehci, flags);
     163         [ #  # ]:          0 :         if (!ehci->async) {
     164                 :          0 :                 goto fail;
     165                 :            :         }
     166                 :            : 
     167                 :            :         /* ITD for high speed ISO transfers */
     168                 :          0 :         ehci->itd_pool = dma_pool_create ("ehci_itd",
     169                 :            :                         ehci_to_hcd(ehci)->self.sysdev,
     170                 :            :                         sizeof (struct ehci_itd),
     171                 :            :                         32 /* byte alignment (for hw parts) */,
     172                 :            :                         4096 /* can't cross 4K */);
     173         [ #  # ]:          0 :         if (!ehci->itd_pool) {
     174                 :          0 :                 goto fail;
     175                 :            :         }
     176                 :            : 
     177                 :            :         /* SITD for full/low speed split ISO transfers */
     178                 :          0 :         ehci->sitd_pool = dma_pool_create ("ehci_sitd",
     179                 :            :                         ehci_to_hcd(ehci)->self.sysdev,
     180                 :            :                         sizeof (struct ehci_sitd),
     181                 :            :                         32 /* byte alignment (for hw parts) */,
     182                 :            :                         4096 /* can't cross 4K */);
     183         [ #  # ]:          0 :         if (!ehci->sitd_pool) {
     184                 :          0 :                 goto fail;
     185                 :            :         }
     186                 :            : 
     187                 :            :         /* Hardware periodic table */
     188                 :          0 :         ehci->periodic = (__le32 *)
     189                 :          0 :                 dma_alloc_coherent(ehci_to_hcd(ehci)->self.sysdev,
     190                 :          0 :                         ehci->periodic_size * sizeof(__le32),
     191                 :            :                         &ehci->periodic_dma, flags);
     192         [ #  # ]:          0 :         if (ehci->periodic == NULL) {
     193                 :          0 :                 goto fail;
     194                 :            :         }
     195                 :            : 
     196         [ #  # ]:          0 :         if (ehci->use_dummy_qh) {
     197                 :          0 :                 struct ehci_qh_hw       *hw;
     198                 :          0 :                 ehci->dummy = ehci_qh_alloc(ehci, flags);
     199         [ #  # ]:          0 :                 if (!ehci->dummy)
     200                 :          0 :                         goto fail;
     201                 :            : 
     202                 :          0 :                 hw = ehci->dummy->hw;
     203                 :          0 :                 hw->hw_next = EHCI_LIST_END(ehci);
     204                 :          0 :                 hw->hw_qtd_next = EHCI_LIST_END(ehci);
     205                 :          0 :                 hw->hw_alt_next = EHCI_LIST_END(ehci);
     206                 :          0 :                 ehci->dummy->hw = hw;
     207                 :            : 
     208         [ #  # ]:          0 :                 for (i = 0; i < ehci->periodic_size; i++)
     209                 :          0 :                         ehci->periodic[i] = cpu_to_hc32(ehci,
     210                 :          0 :                                         ehci->dummy->qh_dma);
     211                 :            :         } else {
     212         [ #  # ]:          0 :                 for (i = 0; i < ehci->periodic_size; i++)
     213                 :          0 :                         ehci->periodic[i] = EHCI_LIST_END(ehci);
     214                 :            :         }
     215                 :            : 
     216                 :            :         /* software shadow of hardware table */
     217                 :          0 :         ehci->pshadow = kcalloc(ehci->periodic_size, sizeof(void *), flags);
     218         [ #  # ]:          0 :         if (ehci->pshadow != NULL)
     219                 :            :                 return 0;
     220                 :            : 
     221                 :          0 : fail:
     222                 :          0 :         ehci_dbg (ehci, "couldn't init memory\n");
     223                 :          0 :         ehci_mem_cleanup (ehci);
     224                 :          0 :         return -ENOMEM;
     225                 :            : }

Generated by: LCOV version 1.14