pm8001: add a new spinlock to protect the CCB
authorTomas Henzl <thenzl@redhat.com>
Wed, 9 Jul 2014 11:51:01 +0000 (17:21 +0530)
committerChristoph Hellwig <hch@lst.de>
Fri, 25 Jul 2014 21:17:04 +0000 (17:17 -0400)
Patch adds a new spinlock to protect the ccb management.
It may happen that concurrent threads become the same tag value
from the 'alloc' function', the spinlock prevents this situation.

Signed-off-by: Tomas Henzl <thenzl@redhat.com>
Acked-by: Suresh Thiagarajan <Suresh.Thiagarajan@pmcs.com>
Acked-by: Jack Wang <xjtuwjp@gmail.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
drivers/scsi/pm8001/pm8001_init.c
drivers/scsi/pm8001/pm8001_sas.c
drivers/scsi/pm8001/pm8001_sas.h

index aad060a..acef7d6 100644 (file)
@@ -246,6 +246,7 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha,
 {
        int i;
        spin_lock_init(&pm8001_ha->lock);
+       spin_lock_init(&pm8001_ha->bitmap_lock);
        PM8001_INIT_DBG(pm8001_ha,
                pm8001_printk("pm8001_alloc: PHY:%x\n",
                                pm8001_ha->chip->n_phy));
index be55859..34cea82 100644 (file)
@@ -77,11 +77,16 @@ inline int pm8001_tag_alloc(struct pm8001_hba_info *pm8001_ha, u32 *tag_out)
 {
        unsigned int tag;
        void *bitmap = pm8001_ha->tags;
+       unsigned long flags;
 
+       spin_lock_irqsave(&pm8001_ha->bitmap_lock, flags);
        tag = find_first_zero_bit(bitmap, pm8001_ha->tags_num);
-       if (tag >= pm8001_ha->tags_num)
+       if (tag >= pm8001_ha->tags_num) {
+               spin_unlock_irqrestore(&pm8001_ha->bitmap_lock, flags);
                return -SAS_QUEUE_FULL;
+       }
        set_bit(tag, bitmap);
+       spin_unlock_irqrestore(&pm8001_ha->bitmap_lock, flags);
        *tag_out = tag;
        return 0;
 }
index 14106ad..f6b2ac5 100644 (file)
@@ -475,6 +475,7 @@ struct pm8001_hba_info {
        struct list_head        list;
        unsigned long           flags;
        spinlock_t              lock;/* host-wide lock */
+       spinlock_t              bitmap_lock;
        struct pci_dev          *pdev;/* our device */
        struct device           *dev;
        struct pm8001_hba_memspace io_mem[6];