Author: zbb
Date: Thu Feb 11 12:03:11 2016
New Revision: 295518
URL: https://svnweb.freebsd.org/changeset/base/295518

Log:
  Implement finer locking in ITS
  
  - Change locks' names to be more suitable
  - Don't use blocking mutex. Lock only basic operations such
    as lists or bitmaps modifications.
  
  Reviewed by:   wma
  Obtained from: Semihalf
  Sponsored by:  Cavium
  Differential Revision: https://reviews.freebsd.org/D5230

Modified:
  head/sys/arm64/arm64/gic_v3_its.c
  head/sys/arm64/arm64/gic_v3_var.h

Modified: head/sys/arm64/arm64/gic_v3_its.c
==============================================================================
--- head/sys/arm64/arm64/gic_v3_its.c   Thu Feb 11 12:01:33 2016        
(r295517)
+++ head/sys/arm64/arm64/gic_v3_its.c   Thu Feb 11 12:03:11 2016        
(r295518)
@@ -197,9 +197,9 @@ gic_v3_its_attach(device_t dev)
         * Initialize sleep & spin mutex for ITS
         */
        /* Protects ITS device list and assigned LPIs bitmaps. */
-       mtx_init(&sc->its_mtx, "ITS sleep lock", NULL, MTX_DEF);
+       mtx_init(&sc->its_dev_lock, "ITS dev lock", NULL, MTX_SPIN);
        /* Protects access to ITS command circular buffer. */
-       mtx_init(&sc->its_spin_mtx, "ITS spin lock", NULL, MTX_SPIN);
+       mtx_init(&sc->its_cmd_lock, "ITS cmd lock", NULL, MTX_SPIN);
 
        rid = 0;
        sc->its_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
@@ -1181,7 +1181,7 @@ its_cmd_alloc_locked(struct gic_v3_its_s
         */
        us_left = 1000000;
 
-       mtx_assert(&sc->its_spin_mtx, MA_OWNED);
+       mtx_assert(&sc->its_cmd_lock, MA_OWNED);
        while (its_cmd_queue_full(sc)) {
                if (us_left-- == 0) {
                        /* Timeout while waiting for free command */
@@ -1334,11 +1334,11 @@ its_cmd_send(struct gic_v3_its_softc *sc
        struct its_cmd_desc desc_sync;
        uint64_t target, cwriter;
 
-       mtx_lock_spin(&sc->its_spin_mtx);
+       mtx_lock_spin(&sc->its_cmd_lock);
        cmd = its_cmd_alloc_locked(sc);
        if (cmd == NULL) {
                device_printf(sc->dev, "could not allocate ITS command\n");
-               mtx_unlock_spin(&sc->its_spin_mtx);
+               mtx_unlock_spin(&sc->its_cmd_lock);
                return (EBUSY);
        }
 
@@ -1360,7 +1360,7 @@ end:
        cwriter = its_cmd_cwriter_offset(sc, sc->its_cmdq_write);
        gic_its_write(sc, 8, GITS_CWRITER, cwriter);
        cmd_write = sc->its_cmdq_write;
-       mtx_unlock_spin(&sc->its_spin_mtx);
+       mtx_unlock_spin(&sc->its_cmd_lock);
 
        its_cmd_wait_completion(sc, cmd, cmd_write);
 
@@ -1372,7 +1372,7 @@ its_device_find_locked(struct gic_v3_its
 {
        struct its_dev *its_dev;
 
-       mtx_assert(&sc->its_mtx, MA_OWNED);
+       mtx_assert(&sc->its_dev_lock, MA_OWNED);
        /* Find existing device if any */
        TAILQ_FOREACH(its_dev, &sc->its_dev_list, entry) {
                if (its_dev->pci_dev == pci_dev)
@@ -1383,7 +1383,7 @@ its_device_find_locked(struct gic_v3_its
 }
 
 static struct its_dev *
-its_device_alloc_locked(struct gic_v3_its_softc *sc, device_t pci_dev,
+its_device_alloc(struct gic_v3_its_softc *sc, device_t pci_dev,
     u_int nvecs)
 {
        struct its_dev *newdev;
@@ -1391,10 +1391,12 @@ its_device_alloc_locked(struct gic_v3_it
        uint32_t devid;
        u_int cpuid;
        size_t esize;
+       int err;
 
-       mtx_assert(&sc->its_mtx, MA_OWNED);
+       mtx_lock_spin(&sc->its_dev_lock);
        /* Find existing device if any */
        newdev = its_device_find_locked(sc, pci_dev);
+       mtx_unlock_spin(&sc->its_dev_lock);
        if (newdev != NULL)
                return (newdev);
 
@@ -1408,7 +1410,10 @@ its_device_alloc_locked(struct gic_v3_it
        newdev->pci_dev = pci_dev;
        newdev->devid = devid;
 
-       if (lpi_alloc_chunk(sc, &newdev->lpis, nvecs) != 0) {
+       mtx_lock_spin(&sc->its_dev_lock);
+       err = lpi_alloc_chunk(sc, &newdev->lpis, nvecs);
+       mtx_unlock_spin(&sc->its_dev_lock);
+       if (err != 0) {
                free(newdev, M_GIC_V3_ITS);
                return (NULL);
        }
@@ -1424,7 +1429,9 @@ its_device_alloc_locked(struct gic_v3_it
            roundup2(roundup2(nvecs, 2) * esize, 0x100), M_GIC_V3_ITS,
            (M_NOWAIT | M_ZERO), 0, ~0UL, 0x100, 0);
        if (newdev->itt == 0) {
+               mtx_lock_spin(&sc->its_dev_lock);
                lpi_free_chunk(sc, &newdev->lpis);
+               mtx_unlock_spin(&sc->its_dev_lock);
                free(newdev, M_GIC_V3_ITS);
                return (NULL);
        }
@@ -1436,7 +1443,9 @@ its_device_alloc_locked(struct gic_v3_it
        cpuid = 0;
        newdev->col = sc->its_cols[cpuid];
 
+       mtx_lock_spin(&sc->its_dev_lock);
        TAILQ_INSERT_TAIL(&sc->its_dev_list, newdev, entry);
+       mtx_unlock_spin(&sc->its_dev_lock);
 
        /* Map device to its ITT */
        its_cmd_mapd(sc, newdev, 1);
@@ -1449,7 +1458,7 @@ its_device_asign_lpi_locked(struct gic_v
     struct its_dev *its_dev, u_int *irq)
 {
 
-       mtx_assert(&sc->its_mtx, MA_OWNED);
+       mtx_assert(&sc->its_dev_lock, MA_OWNED);
        if (its_dev->lpis.lpi_free == 0) {
                panic("Requesting more LPIs than allocated for this device. "
                    "LPI num: %u, free %u", its_dev->lpis.lpi_num,
@@ -1612,21 +1621,19 @@ gic_v3_its_alloc_msix(device_t dev, devi
 
        sc = device_get_softc(dev);
 
-       mtx_lock(&sc->its_mtx);
        nvecs = PCI_MSIX_NUM(pci_dev);
 
        /*
         * Allocate device as seen by ITS if not already available.
         * Notice that MSI-X interrupts are allocated on one-by-one basis.
         */
-       its_dev = its_device_alloc_locked(sc, pci_dev, nvecs);
-       if (its_dev == NULL) {
-               mtx_unlock(&sc->its_mtx);
+       its_dev = its_device_alloc(sc, pci_dev, nvecs);
+       if (its_dev == NULL)
                return (ENOMEM);
-       }
 
+       mtx_lock_spin(&sc->its_dev_lock);
        its_device_asign_lpi_locked(sc, its_dev, irq);
-       mtx_unlock(&sc->its_mtx);
+       mtx_unlock_spin(&sc->its_dev_lock);
 
        return (0);
 }
@@ -1640,18 +1647,16 @@ gic_v3_its_alloc_msi(device_t dev, devic
        sc = device_get_softc(dev);
 
        /* Allocate device as seen by ITS if not already available. */
-       mtx_lock(&sc->its_mtx);
-       its_dev = its_device_alloc_locked(sc, pci_dev, count);
-       if (its_dev == NULL) {
-               mtx_unlock(&sc->its_mtx);
+       its_dev = its_device_alloc(sc, pci_dev, count);
+       if (its_dev == NULL)
                return (ENOMEM);
-       }
 
+       mtx_lock_spin(&sc->its_dev_lock);
        for (; count > 0; count--) {
                its_device_asign_lpi_locked(sc, its_dev, irqs);
                irqs++;
        }
-       mtx_unlock(&sc->its_mtx);
+       mtx_unlock_spin(&sc->its_dev_lock);
 
        return (0);
 }
@@ -1668,9 +1673,9 @@ gic_v3_its_map_msi(device_t dev, device_
 
        sc = device_get_softc(dev);
        /* Verify that this device is allocated and owns this LPI */
-       mtx_lock(&sc->its_mtx);
-       its_dev = its_device_find_locked(sc, pci_dev);
-       mtx_unlock(&sc->its_mtx);
+       mtx_lock_spin(&sc->its_dev_lock);
+       its_dev = its_device_find_locked(sc, pci_dev, 0);
+       mtx_unlock_spin(&sc->its_dev_lock);
        if (its_dev == NULL)
                return (EINVAL);
 

Modified: head/sys/arm64/arm64/gic_v3_var.h
==============================================================================
--- head/sys/arm64/arm64/gic_v3_var.h   Thu Feb 11 12:01:33 2016        
(r295517)
+++ head/sys/arm64/arm64/gic_v3_var.h   Thu Feb 11 12:03:11 2016        
(r295518)
@@ -230,8 +230,8 @@ struct gic_v3_its_softc {
        unsigned long *         its_lpi_bitmap;
        uint32_t                its_lpi_maxid;
 
-       struct mtx              its_mtx;
-       struct mtx              its_spin_mtx;
+       struct mtx              its_dev_lock;
+       struct mtx              its_cmd_lock;
 
        uint32_t                its_socket;     /* Socket number ITS is 
attached to */
 };
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to