Home | History | Annotate | Line # | Download | only in ixgbe
ixgbe_netbsd.c revision 1.13
      1  1.13  riastrad /* $NetBSD: ixgbe_netbsd.c,v 1.13 2020/02/01 02:33:08 riastradh Exp $ */
      2   1.1    dyoung /*
      3   1.1    dyoung  * Copyright (c) 2011 The NetBSD Foundation, Inc.
      4   1.1    dyoung  * All rights reserved.
      5   1.1    dyoung  *
      6   1.1    dyoung  * This code is derived from software contributed to The NetBSD Foundation
      7   1.1    dyoung  * by Coyote Point Systems, Inc.
      8   1.1    dyoung  *
      9   1.1    dyoung  * Redistribution and use in source and binary forms, with or without
     10   1.1    dyoung  * modification, are permitted provided that the following conditions
     11   1.1    dyoung  * are met:
     12   1.1    dyoung  * 1. Redistributions of source code must retain the above copyright
     13   1.1    dyoung  *    notice, this list of conditions and the following disclaimer.
     14   1.1    dyoung  * 2. Redistributions in binary form must reproduce the above copyright
     15   1.1    dyoung  *    notice, this list of conditions and the following disclaimer in the
     16   1.1    dyoung  *    documentation and/or other materials provided with the distribution.
     17   1.1    dyoung  *
     18   1.1    dyoung  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     19   1.1    dyoung  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     20   1.1    dyoung  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     21   1.1    dyoung  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     22   1.1    dyoung  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     23   1.1    dyoung  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     24   1.1    dyoung  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     25   1.1    dyoung  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     26   1.1    dyoung  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     27   1.1    dyoung  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     28   1.1    dyoung  * POSSIBILITY OF SUCH DAMAGE.
     29   1.1    dyoung  */
     30   1.1    dyoung #include <sys/param.h>
     31   1.1    dyoung 
     32   1.1    dyoung #include <sys/atomic.h>
     33   1.1    dyoung #include <sys/bus.h>
     34   1.1    dyoung #include <sys/condvar.h>
     35   1.1    dyoung #include <sys/cpu.h>
     36   1.1    dyoung #include <sys/kmem.h>
     37   1.1    dyoung #include <sys/mbuf.h>
     38   1.1    dyoung #include <sys/mutex.h>
     39   1.1    dyoung #include <sys/queue.h>
     40   1.1    dyoung #include <sys/workqueue.h>
     41   1.4   msaitoh #include <dev/pci/pcivar.h>
     42   1.1    dyoung 
     43   1.7   msaitoh #include "ixgbe.h"
     44   1.1    dyoung 
     45   1.1    dyoung void
     46   1.1    dyoung ixgbe_dma_tag_destroy(ixgbe_dma_tag_t *dt)
     47   1.1    dyoung {
     48   1.1    dyoung 	kmem_free(dt, sizeof(*dt));
     49   1.1    dyoung }
     50   1.1    dyoung 
     51   1.1    dyoung int
     52   1.1    dyoung ixgbe_dma_tag_create(bus_dma_tag_t dmat, bus_size_t alignment,
     53   1.1    dyoung     bus_size_t boundary, bus_size_t maxsize, int nsegments,
     54   1.1    dyoung     bus_size_t maxsegsize, int flags, ixgbe_dma_tag_t **dtp)
     55   1.1    dyoung {
     56   1.1    dyoung 	ixgbe_dma_tag_t *dt;
     57   1.1    dyoung 
     58   1.1    dyoung 	*dtp = NULL;
     59   1.1    dyoung 
     60   1.6       chs 	dt = kmem_zalloc(sizeof(*dt), KM_SLEEP);
     61   1.1    dyoung 	dt->dt_dmat = dmat;
     62   1.1    dyoung 	dt->dt_alignment = alignment;
     63   1.1    dyoung 	dt->dt_boundary = boundary;
     64   1.1    dyoung 	dt->dt_maxsize = maxsize;
     65   1.1    dyoung 	dt->dt_nsegments = nsegments;
     66   1.1    dyoung 	dt->dt_maxsegsize = maxsegsize;
     67   1.1    dyoung 	dt->dt_flags = flags;
     68   1.1    dyoung 	*dtp = dt;
     69   1.1    dyoung 
     70   1.1    dyoung 	return 0;
     71   1.1    dyoung }
     72   1.1    dyoung 
     73   1.1    dyoung void
     74   1.1    dyoung ixgbe_dmamap_destroy(ixgbe_dma_tag_t *dt, bus_dmamap_t dmam)
     75   1.1    dyoung {
     76   1.1    dyoung 	bus_dmamap_destroy(dt->dt_dmat, dmam);
     77   1.1    dyoung }
     78   1.1    dyoung 
     79   1.1    dyoung void
     80   1.1    dyoung ixgbe_dmamap_sync(ixgbe_dma_tag_t *dt, bus_dmamap_t dmam, int ops)
     81   1.1    dyoung {
     82   1.1    dyoung         bus_dmamap_sync(dt->dt_dmat, dmam, 0, dt->dt_maxsize, ops);
     83   1.1    dyoung }
     84   1.1    dyoung 
     85   1.1    dyoung void
     86   1.1    dyoung ixgbe_dmamap_unload(ixgbe_dma_tag_t *dt, bus_dmamap_t dmam)
     87   1.1    dyoung {
     88   1.1    dyoung 	bus_dmamap_unload(dt->dt_dmat, dmam);
     89   1.1    dyoung }
     90   1.1    dyoung 
     91   1.1    dyoung int
     92   1.1    dyoung ixgbe_dmamap_create(ixgbe_dma_tag_t *dt, int flags, bus_dmamap_t *dmamp)
     93   1.1    dyoung {
     94   1.1    dyoung 	return bus_dmamap_create(dt->dt_dmat, dt->dt_maxsize, dt->dt_nsegments,
     95   1.1    dyoung 	    dt->dt_maxsegsize, dt->dt_boundary, flags, dmamp);
     96   1.1    dyoung }
     97   1.1    dyoung 
     98   1.1    dyoung static void
     99   1.1    dyoung ixgbe_putext(ixgbe_extmem_t *em)
    100   1.1    dyoung {
    101   1.1    dyoung 	ixgbe_extmem_head_t *eh = em->em_head;
    102   1.1    dyoung 
    103   1.1    dyoung 	mutex_enter(&eh->eh_mtx);
    104   1.1    dyoung 
    105   1.1    dyoung 	TAILQ_INSERT_HEAD(&eh->eh_freelist, em, em_link);
    106   1.1    dyoung 
    107   1.1    dyoung 	mutex_exit(&eh->eh_mtx);
    108   1.1    dyoung 
    109   1.1    dyoung 	return;
    110   1.1    dyoung }
    111   1.1    dyoung 
    112   1.1    dyoung static ixgbe_extmem_t *
    113   1.1    dyoung ixgbe_getext(ixgbe_extmem_head_t *eh, size_t size)
    114   1.1    dyoung {
    115   1.1    dyoung 	ixgbe_extmem_t *em;
    116   1.1    dyoung 
    117   1.1    dyoung 	mutex_enter(&eh->eh_mtx);
    118   1.1    dyoung 
    119   1.1    dyoung 	TAILQ_FOREACH(em, &eh->eh_freelist, em_link) {
    120   1.1    dyoung 		if (em->em_size >= size)
    121   1.1    dyoung 			break;
    122   1.1    dyoung 	}
    123   1.1    dyoung 
    124   1.1    dyoung 	if (em != NULL)
    125   1.1    dyoung 		TAILQ_REMOVE(&eh->eh_freelist, em, em_link);
    126   1.1    dyoung 
    127   1.1    dyoung 	mutex_exit(&eh->eh_mtx);
    128   1.1    dyoung 
    129   1.1    dyoung 	return em;
    130   1.1    dyoung }
    131   1.1    dyoung 
    132   1.1    dyoung static ixgbe_extmem_t *
    133   1.1    dyoung ixgbe_newext(ixgbe_extmem_head_t *eh, bus_dma_tag_t dmat, size_t size)
    134   1.1    dyoung {
    135   1.1    dyoung 	ixgbe_extmem_t *em;
    136   1.1    dyoung 	int nseg, rc;
    137   1.1    dyoung 
    138   1.3   msaitoh 	em = kmem_zalloc(sizeof(*em), KM_SLEEP);
    139   1.1    dyoung 
    140   1.1    dyoung 	rc = bus_dmamem_alloc(dmat, size, PAGE_SIZE, 0, &em->em_seg, 1, &nseg,
    141   1.3   msaitoh 	    BUS_DMA_WAITOK);
    142   1.1    dyoung 
    143   1.1    dyoung 	if (rc != 0)
    144   1.1    dyoung 		goto post_zalloc_err;
    145   1.1    dyoung 
    146   1.1    dyoung 	rc = bus_dmamem_map(dmat, &em->em_seg, 1, size, &em->em_vaddr,
    147   1.3   msaitoh 	    BUS_DMA_WAITOK);
    148   1.1    dyoung 
    149   1.1    dyoung 	if (rc != 0)
    150   1.1    dyoung 		goto post_dmamem_err;
    151   1.1    dyoung 
    152   1.1    dyoung 	em->em_dmat = dmat;
    153   1.1    dyoung 	em->em_size = size;
    154   1.1    dyoung 	em->em_head = eh;
    155   1.1    dyoung 
    156   1.1    dyoung 	return em;
    157   1.1    dyoung post_dmamem_err:
    158   1.1    dyoung 	bus_dmamem_free(dmat, &em->em_seg, 1);
    159   1.1    dyoung post_zalloc_err:
    160   1.1    dyoung 	kmem_free(em, sizeof(*em));
    161   1.1    dyoung 	return NULL;
    162   1.1    dyoung }
    163   1.1    dyoung 
    164  1.11   msaitoh static void
    165  1.11   msaitoh ixgbe_jcl_freeall(struct adapter *adapter, struct rx_ring *rxr)
    166  1.11   msaitoh {
    167  1.11   msaitoh 	ixgbe_extmem_head_t *eh = &rxr->jcl_head;
    168  1.11   msaitoh 	ixgbe_extmem_t *em;
    169  1.11   msaitoh 	bus_dma_tag_t dmat = rxr->ptag->dt_dmat;
    170  1.11   msaitoh 
    171  1.11   msaitoh 	while ((em = ixgbe_getext(eh, 0)) != NULL) {
    172  1.11   msaitoh 		KASSERT(em->em_vaddr != NULL);
    173  1.11   msaitoh 		bus_dmamem_unmap(dmat, em->em_vaddr, em->em_size);
    174  1.11   msaitoh 		bus_dmamem_free(dmat, &em->em_seg, 1);
    175  1.11   msaitoh 		memset(em, 0, sizeof(*em));
    176  1.11   msaitoh 		kmem_free(em, sizeof(*em));
    177  1.11   msaitoh 	}
    178  1.11   msaitoh }
    179  1.11   msaitoh 
    180   1.1    dyoung void
    181   1.8   msaitoh ixgbe_jcl_reinit(struct adapter *adapter, bus_dma_tag_t dmat,
    182   1.8   msaitoh     struct rx_ring *rxr, int nbuf, size_t size)
    183   1.1    dyoung {
    184   1.8   msaitoh 	ixgbe_extmem_head_t *eh = &rxr->jcl_head;
    185   1.7   msaitoh 	ixgbe_extmem_t *em;
    186   1.1    dyoung 	int i;
    187   1.1    dyoung 
    188   1.1    dyoung 	if (!eh->eh_initialized) {
    189   1.1    dyoung 		TAILQ_INIT(&eh->eh_freelist);
    190   1.1    dyoung 		mutex_init(&eh->eh_mtx, MUTEX_DEFAULT, IPL_NET);
    191   1.1    dyoung 		eh->eh_initialized = true;
    192   1.1    dyoung 	}
    193   1.1    dyoung 
    194   1.7   msaitoh 	/*
    195   1.7   msaitoh 	 *  Check previous parameters. If it's not required to reinit, just
    196   1.7   msaitoh 	 * return.
    197   1.7   msaitoh 	 *
    198   1.7   msaitoh 	 *  Note that the num_rx_desc is currently fixed value. It's never
    199   1.7   msaitoh 	 * changed after device is attached.
    200   1.7   msaitoh 	 */
    201   1.8   msaitoh 	if ((rxr->last_rx_mbuf_sz == rxr->mbuf_sz)
    202   1.8   msaitoh 	    && (rxr->last_num_rx_desc == adapter->num_rx_desc))
    203   1.7   msaitoh 		return;
    204   1.7   msaitoh 
    205   1.7   msaitoh 	/* Free all dmamem */
    206  1.11   msaitoh 	ixgbe_jcl_freeall(adapter, rxr);
    207   1.1    dyoung 
    208   1.1    dyoung 	for (i = 0; i < nbuf; i++) {
    209   1.1    dyoung 		if ((em = ixgbe_newext(eh, dmat, size)) == NULL) {
    210  1.10   msaitoh 			device_printf(adapter->dev,
    211  1.10   msaitoh 			    "%s: only %d of %d jumbo buffers allocated\n",
    212   1.1    dyoung 			    __func__, i, nbuf);
    213   1.1    dyoung 			break;
    214   1.1    dyoung 		}
    215   1.1    dyoung 		ixgbe_putext(em);
    216   1.1    dyoung 	}
    217   1.7   msaitoh 
    218   1.7   msaitoh 	/* Keep current parameters */
    219   1.8   msaitoh 	rxr->last_rx_mbuf_sz = adapter->rx_mbuf_sz;
    220   1.8   msaitoh 	rxr->last_num_rx_desc = adapter->num_rx_desc;
    221   1.1    dyoung }
    222   1.1    dyoung 
    223  1.11   msaitoh void
    224  1.11   msaitoh ixgbe_jcl_destroy(struct adapter *adapter, struct rx_ring *rxr)
    225  1.11   msaitoh {
    226  1.11   msaitoh 	ixgbe_extmem_head_t *eh = &rxr->jcl_head;
    227  1.11   msaitoh 
    228  1.12   msaitoh 	if (eh->eh_initialized) {
    229  1.12   msaitoh 		/* Free all dmamem */
    230  1.12   msaitoh 		ixgbe_jcl_freeall(adapter, rxr);
    231  1.11   msaitoh 
    232  1.11   msaitoh 		mutex_destroy(&eh->eh_mtx);
    233  1.11   msaitoh 		eh->eh_initialized = false;
    234  1.11   msaitoh 	}
    235  1.11   msaitoh }
    236  1.11   msaitoh 
    237  1.11   msaitoh 
    238   1.1    dyoung static void
    239   1.1    dyoung ixgbe_jcl_free(struct mbuf *m, void *buf, size_t size, void *arg)
    240   1.1    dyoung {
    241   1.1    dyoung 	ixgbe_extmem_t *em = arg;
    242   1.1    dyoung 
    243   1.1    dyoung 	KASSERT(em->em_size == size);
    244   1.1    dyoung 
    245   1.1    dyoung 	ixgbe_putext(em);
    246   1.1    dyoung 	/* this is an abstraction violation, but it does not lead to a
    247   1.1    dyoung 	 * double-free
    248   1.1    dyoung 	 */
    249   1.1    dyoung 	if (__predict_true(m != NULL)) {
    250   1.1    dyoung 		KASSERT(m->m_type != MT_FREE);
    251   1.1    dyoung 		m->m_type = MT_FREE;
    252   1.1    dyoung 		pool_cache_put(mb_cache, m);
    253   1.1    dyoung 	}
    254   1.1    dyoung }
    255   1.1    dyoung 
    256   1.1    dyoung /* XXX need to wait for the system to finish with each jumbo mbuf and
    257   1.1    dyoung  * free it before detaching the driver from the device.
    258   1.1    dyoung  */
    259   1.1    dyoung struct mbuf *
    260   1.1    dyoung ixgbe_getjcl(ixgbe_extmem_head_t *eh, int nowait /* M_DONTWAIT */,
    261   1.1    dyoung     int type /* MT_DATA */, int flags /* M_PKTHDR */, size_t size)
    262   1.1    dyoung {
    263   1.1    dyoung 	ixgbe_extmem_t *em;
    264   1.1    dyoung 	struct mbuf *m;
    265   1.1    dyoung 
    266   1.1    dyoung 	if ((flags & M_PKTHDR) != 0)
    267   1.1    dyoung 		m = m_gethdr(nowait, type);
    268   1.1    dyoung 	else
    269   1.1    dyoung 		m = m_get(nowait, type);
    270   1.1    dyoung 
    271   1.1    dyoung 	if (m == NULL)
    272   1.1    dyoung 		return NULL;
    273   1.1    dyoung 
    274   1.1    dyoung 	em = ixgbe_getext(eh, size);
    275   1.1    dyoung 	if (em == NULL) {
    276   1.1    dyoung 		m_freem(m);
    277   1.1    dyoung 		return NULL;
    278   1.1    dyoung 	}
    279   1.1    dyoung 
    280   1.1    dyoung 	MEXTADD(m, em->em_vaddr, em->em_size, M_DEVBUF, &ixgbe_jcl_free, em);
    281   1.1    dyoung 
    282   1.1    dyoung 	if ((m->m_flags & M_EXT) == 0) {
    283   1.1    dyoung 		ixgbe_putext(em);
    284   1.1    dyoung 		m_freem(m);
    285   1.1    dyoung 		return NULL;
    286   1.1    dyoung 	}
    287   1.1    dyoung 
    288   1.1    dyoung 	return m;
    289   1.1    dyoung }
    290   1.4   msaitoh 
    291   1.4   msaitoh void
    292   1.4   msaitoh ixgbe_pci_enable_busmaster(pci_chipset_tag_t pc, pcitag_t tag)
    293   1.4   msaitoh {
    294   1.4   msaitoh 	pcireg_t	pci_cmd_word;
    295   1.4   msaitoh 
    296   1.4   msaitoh 	pci_cmd_word = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
    297   1.4   msaitoh 	if (!(pci_cmd_word & PCI_COMMAND_MASTER_ENABLE)) {
    298   1.4   msaitoh 		pci_cmd_word |= PCI_COMMAND_MASTER_ENABLE;
    299   1.4   msaitoh 		pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, pci_cmd_word);
    300   1.4   msaitoh 	}
    301   1.4   msaitoh }
    302   1.9   msaitoh 
    303   1.9   msaitoh u_int
    304   1.9   msaitoh atomic_load_acq_uint(volatile u_int *p)
    305   1.9   msaitoh {
    306  1.13  riastrad 	return atomic_load_acquire(p);
    307   1.9   msaitoh }
    308