Message ID | 20201005145011.23674-2-Viswas.G@microchip.com.com |
---|---|
State | Superseded |
Headers | show |
Series | [V2,1/4] pm80xx: Increase number of supported queues. | expand |
On Mon, Oct 5, 2020 at 4:40 PM Viswas G <Viswas.G@microchip.com.com> wrote: > > From: Viswas G <Viswas.G@microchip.com> > > Current driver uses fixed number of Inbound and Outbound queues and all > of the IO, TMF and internal requests are submitted through those. Global > spin lock is used to control the shared access. This will create a > lock contention and it is real bottleneck in the IO path. To avoid this, > the number of supported Inbound and outbound queues is increased to 64, > and the number of queues used are decided based on number of CPU cores > online and number of MSIX allocated. Also, added locks per queue > instead of using the global lock. > > Signed-off-by: Viswas G <Viswas.G@microchip.com> > Signed-off-by: Ruksar Devadi <Ruksar.devadi@microchip.com> looks good. Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com> > --- > drivers/scsi/pm8001/pm8001_ctl.c | 6 +- > drivers/scsi/pm8001/pm8001_defs.h | 17 +++--- > drivers/scsi/pm8001/pm8001_hwi.c | 32 ++++++----- > drivers/scsi/pm8001/pm8001_init.c | 117 ++++++++++++++++++++++++-------------- > drivers/scsi/pm8001/pm8001_sas.h | 11 +++- > drivers/scsi/pm8001/pm80xx_hwi.c | 81 +++++++++++++++----------- > 6 files changed, 160 insertions(+), 104 deletions(-) > > diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c > index 77c805db2724..3587f7c8a428 100644 > --- a/drivers/scsi/pm8001/pm8001_ctl.c > +++ b/drivers/scsi/pm8001/pm8001_ctl.c > @@ -408,9 +408,10 @@ static ssize_t pm8001_ctl_ib_queue_log_show(struct device *cdev, > int offset; > char *str = buf; > int start = 0; > + u32 ib_offset = pm8001_ha->ib_offset; > #define IB_MEMMAP(c) \ > (*(u32 *)((u8 *)pm8001_ha-> \ > - memoryMap.region[IB].virt_ptr + \ > + memoryMap.region[ib_offset].virt_ptr + \ > pm8001_ha->evtlog_ib_offset + (c))) > > for (offset = 0; offset < IB_OB_READ_TIMES; offset++) { > @@ -442,9 +443,10 @@ static ssize_t pm8001_ctl_ob_queue_log_show(struct device *cdev, > int offset; > char *str = buf; > int start = 0; > + u32 ob_offset = pm8001_ha->ob_offset; > #define OB_MEMMAP(c) \ > (*(u32 *)((u8 *)pm8001_ha-> \ > - memoryMap.region[OB].virt_ptr + \ > + memoryMap.region[ob_offset].virt_ptr + \ > pm8001_ha->evtlog_ob_offset + (c))) > > for (offset = 0; offset < IB_OB_READ_TIMES; offset++) { > diff --git a/drivers/scsi/pm8001/pm8001_defs.h b/drivers/scsi/pm8001/pm8001_defs.h > index 1c7f15fd69ce..a4f52a5a449e 100644 > --- a/drivers/scsi/pm8001/pm8001_defs.h > +++ b/drivers/scsi/pm8001/pm8001_defs.h > @@ -77,10 +77,8 @@ enum port_type { > /* driver compile-time configuration */ > #define PM8001_MAX_CCB 256 /* max ccbs supported */ > #define PM8001_MPI_QUEUE 1024 /* maximum mpi queue entries */ > -#define PM8001_MAX_INB_NUM 1 > -#define PM8001_MAX_OUTB_NUM 1 > -#define PM8001_MAX_SPCV_INB_NUM 1 > -#define PM8001_MAX_SPCV_OUTB_NUM 4 > +#define PM8001_MAX_INB_NUM 64 > +#define PM8001_MAX_OUTB_NUM 64 > #define PM8001_CAN_QUEUE 508 /* SCSI Queue depth */ > > /* Inbound/Outbound queue size */ > @@ -94,11 +92,6 @@ enum port_type { > #define PM8001_MAX_MSIX_VEC 64 /* max msi-x int for spcv/ve */ > > #define USI_MAX_MEMCNT_BASE 5 > -#define IB (USI_MAX_MEMCNT_BASE + 1) > -#define CI (IB + PM8001_MAX_SPCV_INB_NUM) > -#define OB (CI + PM8001_MAX_SPCV_INB_NUM) > -#define PI (OB + PM8001_MAX_SPCV_OUTB_NUM) > -#define USI_MAX_MEMCNT (PI + PM8001_MAX_SPCV_OUTB_NUM) > #define CONFIG_SCSI_PM8001_MAX_DMA_SG 528 > #define PM8001_MAX_DMA_SG CONFIG_SCSI_PM8001_MAX_DMA_SG > enum memory_region_num { > @@ -112,6 +105,12 @@ enum memory_region_num { > }; > #define PM8001_EVENT_LOG_SIZE (128 * 1024) > > +/** > + * maximum DMA memory regions(number of IBQ + number of IBQ CI > + * + number of OBQ + number of OBQ PI) > + */ > +#define USI_MAX_MEMCNT (USI_MAX_MEMCNT_BASE + 1 + ((2 * PM8001_MAX_INB_NUM) \ > + + (2 * PM8001_MAX_OUTB_NUM))) > /*error code*/ > enum mpi_err { > MPI_IO_STATUS_SUCCESS = 0x0, > diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c > index e9a939230b15..e9106575a30f 100644 > --- a/drivers/scsi/pm8001/pm8001_hwi.c > +++ b/drivers/scsi/pm8001/pm8001_hwi.c > @@ -189,6 +189,10 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha) > u32 offsetib, offsetob; > void __iomem *addressib = pm8001_ha->inbnd_q_tbl_addr; > void __iomem *addressob = pm8001_ha->outbnd_q_tbl_addr; > + u32 ib_offset = pm8001_ha->ib_offset; > + u32 ob_offset = pm8001_ha->ob_offset; > + u32 ci_offset = pm8001_ha->ci_offset; > + u32 pi_offset = pm8001_ha->pi_offset; > > pm8001_ha->main_cfg_tbl.pm8001_tbl.inbound_q_nppd_hppd = 0; > pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_hw_event_pid0_3 = 0; > @@ -223,19 +227,19 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha) > pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt = > PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x00<<30); > pm8001_ha->inbnd_q_tbl[i].upper_base_addr = > - pm8001_ha->memoryMap.region[IB + i].phys_addr_hi; > + pm8001_ha->memoryMap.region[ib_offset + i].phys_addr_hi; > pm8001_ha->inbnd_q_tbl[i].lower_base_addr = > - pm8001_ha->memoryMap.region[IB + i].phys_addr_lo; > + pm8001_ha->memoryMap.region[ib_offset + i].phys_addr_lo; > pm8001_ha->inbnd_q_tbl[i].base_virt = > - (u8 *)pm8001_ha->memoryMap.region[IB + i].virt_ptr; > + (u8 *)pm8001_ha->memoryMap.region[ib_offset + i].virt_ptr; > pm8001_ha->inbnd_q_tbl[i].total_length = > - pm8001_ha->memoryMap.region[IB + i].total_len; > + pm8001_ha->memoryMap.region[ib_offset + i].total_len; > pm8001_ha->inbnd_q_tbl[i].ci_upper_base_addr = > - pm8001_ha->memoryMap.region[CI + i].phys_addr_hi; > + pm8001_ha->memoryMap.region[ci_offset + i].phys_addr_hi; > pm8001_ha->inbnd_q_tbl[i].ci_lower_base_addr = > - pm8001_ha->memoryMap.region[CI + i].phys_addr_lo; > + pm8001_ha->memoryMap.region[ci_offset + i].phys_addr_lo; > pm8001_ha->inbnd_q_tbl[i].ci_virt = > - pm8001_ha->memoryMap.region[CI + i].virt_ptr; > + pm8001_ha->memoryMap.region[ci_offset + i].virt_ptr; > offsetib = i * 0x20; > pm8001_ha->inbnd_q_tbl[i].pi_pci_bar = > get_pci_bar_index(pm8001_mr32(addressib, > @@ -249,21 +253,21 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha) > pm8001_ha->outbnd_q_tbl[i].element_size_cnt = > PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x01<<30); > pm8001_ha->outbnd_q_tbl[i].upper_base_addr = > - pm8001_ha->memoryMap.region[OB + i].phys_addr_hi; > + pm8001_ha->memoryMap.region[ob_offset + i].phys_addr_hi; > pm8001_ha->outbnd_q_tbl[i].lower_base_addr = > - pm8001_ha->memoryMap.region[OB + i].phys_addr_lo; > + pm8001_ha->memoryMap.region[ob_offset + i].phys_addr_lo; > pm8001_ha->outbnd_q_tbl[i].base_virt = > - (u8 *)pm8001_ha->memoryMap.region[OB + i].virt_ptr; > + (u8 *)pm8001_ha->memoryMap.region[ob_offset + i].virt_ptr; > pm8001_ha->outbnd_q_tbl[i].total_length = > - pm8001_ha->memoryMap.region[OB + i].total_len; > + pm8001_ha->memoryMap.region[ob_offset + i].total_len; > pm8001_ha->outbnd_q_tbl[i].pi_upper_base_addr = > - pm8001_ha->memoryMap.region[PI + i].phys_addr_hi; > + pm8001_ha->memoryMap.region[pi_offset + i].phys_addr_hi; > pm8001_ha->outbnd_q_tbl[i].pi_lower_base_addr = > - pm8001_ha->memoryMap.region[PI + i].phys_addr_lo; > + pm8001_ha->memoryMap.region[pi_offset + i].phys_addr_lo; > pm8001_ha->outbnd_q_tbl[i].interrup_vec_cnt_delay = > 0 | (10 << 16) | (i << 24); > pm8001_ha->outbnd_q_tbl[i].pi_virt = > - pm8001_ha->memoryMap.region[PI + i].virt_ptr; > + pm8001_ha->memoryMap.region[pi_offset + i].virt_ptr; > offsetob = i * 0x24; > pm8001_ha->outbnd_q_tbl[i].ci_pci_bar = > get_pci_bar_index(pm8001_mr32(addressob, > diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c > index 20fa96cbc9d3..c744f846e08d 100644 > --- a/drivers/scsi/pm8001/pm8001_init.c > +++ b/drivers/scsi/pm8001/pm8001_init.c > @@ -264,12 +264,36 @@ static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha); > static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, > const struct pci_device_id *ent) > { > - int i; > + int i, count = 0, rc = 0; > + u32 ci_offset, ib_offset, ob_offset, pi_offset; > + struct inbound_queue_table *circularQ; > + > 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)); > + > + /* Setup Interrupt */ > + rc = pm8001_setup_irq(pm8001_ha); > + if (rc) { > + PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( > + "pm8001_setup_irq failed [ret: %d]\n", rc)); > + goto err_out_shost; > + } > + /* Request Interrupt */ > + rc = pm8001_request_irq(pm8001_ha); > + if (rc) > + goto err_out_shost; > + > + count = pm8001_ha->max_q_num; > + /* Queues are chosen based on the number of cores/msix availability */ > + ib_offset = pm8001_ha->ib_offset = USI_MAX_MEMCNT_BASE + 1; > + ci_offset = pm8001_ha->ci_offset = ib_offset + count; > + ob_offset = pm8001_ha->ob_offset = ci_offset + count; > + pi_offset = pm8001_ha->pi_offset = ob_offset + count; > + pm8001_ha->max_memcnt = pi_offset + count; > + > for (i = 0; i < pm8001_ha->chip->n_phy; i++) { > pm8001_phy_init(pm8001_ha, i); > pm8001_ha->port[i].wide_port_phymap = 0; > @@ -293,54 +317,62 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, > pm8001_ha->memoryMap.region[IOP].total_len = PM8001_EVENT_LOG_SIZE; > pm8001_ha->memoryMap.region[IOP].alignment = 32; > > - for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) { > + for (i = 0; i < count; i++) { > + circularQ = &pm8001_ha->inbnd_q_tbl[i]; > + spin_lock_init(&circularQ->iq_lock); > /* MPI Memory region 3 for consumer Index of inbound queues */ > - pm8001_ha->memoryMap.region[CI+i].num_elements = 1; > - pm8001_ha->memoryMap.region[CI+i].element_size = 4; > - pm8001_ha->memoryMap.region[CI+i].total_len = 4; > - pm8001_ha->memoryMap.region[CI+i].alignment = 4; > + pm8001_ha->memoryMap.region[ci_offset+i].num_elements = 1; > + pm8001_ha->memoryMap.region[ci_offset+i].element_size = 4; > + pm8001_ha->memoryMap.region[ci_offset+i].total_len = 4; > + pm8001_ha->memoryMap.region[ci_offset+i].alignment = 4; > > if ((ent->driver_data) != chip_8001) { > /* MPI Memory region 5 inbound queues */ > - pm8001_ha->memoryMap.region[IB+i].num_elements = > + pm8001_ha->memoryMap.region[ib_offset+i].num_elements = > PM8001_MPI_QUEUE; > - pm8001_ha->memoryMap.region[IB+i].element_size = 128; > - pm8001_ha->memoryMap.region[IB+i].total_len = > + pm8001_ha->memoryMap.region[ib_offset+i].element_size > + = 128; > + pm8001_ha->memoryMap.region[ib_offset+i].total_len = > PM8001_MPI_QUEUE * 128; > - pm8001_ha->memoryMap.region[IB+i].alignment = 128; > + pm8001_ha->memoryMap.region[ib_offset+i].alignment > + = 128; > } else { > - pm8001_ha->memoryMap.region[IB+i].num_elements = > + pm8001_ha->memoryMap.region[ib_offset+i].num_elements = > PM8001_MPI_QUEUE; > - pm8001_ha->memoryMap.region[IB+i].element_size = 64; > - pm8001_ha->memoryMap.region[IB+i].total_len = > + pm8001_ha->memoryMap.region[ib_offset+i].element_size > + = 64; > + pm8001_ha->memoryMap.region[ib_offset+i].total_len = > PM8001_MPI_QUEUE * 64; > - pm8001_ha->memoryMap.region[IB+i].alignment = 64; > + pm8001_ha->memoryMap.region[ib_offset+i].alignment = 64; > } > } > > - for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) { > + for (i = 0; i < count; i++) { > /* MPI Memory region 4 for producer Index of outbound queues */ > - pm8001_ha->memoryMap.region[PI+i].num_elements = 1; > - pm8001_ha->memoryMap.region[PI+i].element_size = 4; > - pm8001_ha->memoryMap.region[PI+i].total_len = 4; > - pm8001_ha->memoryMap.region[PI+i].alignment = 4; > + pm8001_ha->memoryMap.region[pi_offset+i].num_elements = 1; > + pm8001_ha->memoryMap.region[pi_offset+i].element_size = 4; > + pm8001_ha->memoryMap.region[pi_offset+i].total_len = 4; > + pm8001_ha->memoryMap.region[pi_offset+i].alignment = 4; > > if (ent->driver_data != chip_8001) { > /* MPI Memory region 6 Outbound queues */ > - pm8001_ha->memoryMap.region[OB+i].num_elements = > + pm8001_ha->memoryMap.region[ob_offset+i].num_elements = > PM8001_MPI_QUEUE; > - pm8001_ha->memoryMap.region[OB+i].element_size = 128; > - pm8001_ha->memoryMap.region[OB+i].total_len = > + pm8001_ha->memoryMap.region[ob_offset+i].element_size > + = 128; > + pm8001_ha->memoryMap.region[ob_offset+i].total_len = > PM8001_MPI_QUEUE * 128; > - pm8001_ha->memoryMap.region[OB+i].alignment = 128; > + pm8001_ha->memoryMap.region[ob_offset+i].alignment > + = 128; > } else { > /* MPI Memory region 6 Outbound queues */ > - pm8001_ha->memoryMap.region[OB+i].num_elements = > + pm8001_ha->memoryMap.region[ob_offset+i].num_elements = > PM8001_MPI_QUEUE; > - pm8001_ha->memoryMap.region[OB+i].element_size = 64; > - pm8001_ha->memoryMap.region[OB+i].total_len = > + pm8001_ha->memoryMap.region[ob_offset+i].element_size > + = 64; > + pm8001_ha->memoryMap.region[ob_offset+i].total_len = > PM8001_MPI_QUEUE * 64; > - pm8001_ha->memoryMap.region[OB+i].alignment = 64; > + pm8001_ha->memoryMap.region[ob_offset+i].alignment = 64; > } > > } > @@ -369,7 +401,7 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, > pm8001_ha->memoryMap.region[FORENSIC_MEM].total_len = 0x10000; > pm8001_ha->memoryMap.region[FORENSIC_MEM].element_size = 0x10000; > pm8001_ha->memoryMap.region[FORENSIC_MEM].alignment = 0x10000; > - for (i = 0; i < USI_MAX_MEMCNT; i++) { > + for (i = 0; i < pm8001_ha->max_memcnt; i++) { > if (pm8001_mem_alloc(pm8001_ha->pdev, > &pm8001_ha->memoryMap.region[i].virt_ptr, > &pm8001_ha->memoryMap.region[i].phys_addr, > @@ -405,6 +437,8 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, > /* Initialize tags */ > pm8001_tag_init(pm8001_ha); > return 0; > +err_out_shost: > + scsi_remove_host(pm8001_ha->shost); > err_out: > return 1; > } > @@ -899,7 +933,8 @@ static int pm8001_configure_phy_settings(struct pm8001_hba_info *pm8001_ha) > static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha) > { > u32 number_of_intr; > - int rc; > + int rc, cpu_online_count; > + unsigned int allocated_irq_vectors; > > /* SPCv controllers supports 64 msi-x */ > if (pm8001_ha->chip_id == chip_8001) { > @@ -908,13 +943,21 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha) > number_of_intr = PM8001_MAX_MSIX_VEC; > } > > + cpu_online_count = num_online_cpus(); > + number_of_intr = min_t(int, cpu_online_count, number_of_intr); > rc = pci_alloc_irq_vectors(pm8001_ha->pdev, number_of_intr, > number_of_intr, PCI_IRQ_MSIX); > - number_of_intr = rc; > + allocated_irq_vectors = rc; > if (rc < 0) > return rc; > + > + /*Assigns the number of interrupts */ > + number_of_intr = min_t(int, allocated_irq_vectors, number_of_intr); > pm8001_ha->number_of_intr = number_of_intr; > > + /*maximum queue number updating in HBA structure */ > + pm8001_ha->max_q_num = number_of_intr; > + > PM8001_INIT_DBG(pm8001_ha, pm8001_printk( > "pci_alloc_irq_vectors request ret:%d no of intr %d\n", > rc, pm8001_ha->number_of_intr)); > @@ -1069,13 +1112,6 @@ static int pm8001_pci_probe(struct pci_dev *pdev, > rc = -ENOMEM; > goto err_out_free; > } > - /* Setup Interrupt */ > - rc = pm8001_setup_irq(pm8001_ha); > - if (rc) { > - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( > - "pm8001_setup_irq failed [ret: %d]\n", rc)); > - goto err_out_shost; > - } > > PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha); > rc = PM8001_CHIP_DISP->chip_init(pm8001_ha); > @@ -1088,13 +1124,6 @@ static int pm8001_pci_probe(struct pci_dev *pdev, > rc = scsi_add_host(shost, &pdev->dev); > if (rc) > goto err_out_ha_free; > - /* Request Interrupt */ > - rc = pm8001_request_irq(pm8001_ha); > - if (rc) { > - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( > - "pm8001_request_irq failed [ret: %d]\n", rc)); > - goto err_out_shost; > - } > > PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0); > if (pm8001_ha->chip_id != chip_8001) { > diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h > index ae7ba9b3c4bc..bdfce3c3f619 100644 > --- a/drivers/scsi/pm8001/pm8001_sas.h > +++ b/drivers/scsi/pm8001/pm8001_sas.h > @@ -468,6 +468,7 @@ struct inbound_queue_table { > u32 reserved; > __le32 consumer_index; > u32 producer_idx; > + spinlock_t iq_lock; > }; > struct outbound_queue_table { > u32 element_size_cnt; > @@ -524,8 +525,8 @@ struct pm8001_hba_info { > void __iomem *fatal_tbl_addr; /*MPI IVT Table Addr */ > union main_cfg_table main_cfg_tbl; > union general_status_table gs_tbl; > - struct inbound_queue_table inbnd_q_tbl[PM8001_MAX_SPCV_INB_NUM]; > - struct outbound_queue_table outbnd_q_tbl[PM8001_MAX_SPCV_OUTB_NUM]; > + struct inbound_queue_table inbnd_q_tbl[PM8001_MAX_INB_NUM]; > + struct outbound_queue_table outbnd_q_tbl[PM8001_MAX_OUTB_NUM]; > struct sas_phy_attribute_table phy_attr_table; > /* MPI SAS PHY attributes */ > u8 sas_addr[SAS_ADDR_SIZE]; > @@ -561,6 +562,12 @@ struct pm8001_hba_info { > u32 reset_in_progress; > u32 non_fatal_count; > u32 non_fatal_read_length; > + u32 max_q_num; > + u32 ib_offset; > + u32 ob_offset; > + u32 ci_offset; > + u32 pi_offset; > + u32 max_memcnt; > }; > > struct pm8001_work { > diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c > index b42f41d1ed49..26e9e8877107 100644 > --- a/drivers/scsi/pm8001/pm80xx_hwi.c > +++ b/drivers/scsi/pm8001/pm80xx_hwi.c > @@ -720,7 +720,7 @@ static void read_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha) > { > int i; > void __iomem *address = pm8001_ha->inbnd_q_tbl_addr; > - for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) { > + for (i = 0; i < PM8001_MAX_INB_NUM; i++) { > u32 offset = i * 0x20; > pm8001_ha->inbnd_q_tbl[i].pi_pci_bar = > get_pci_bar_index(pm8001_mr32(address, > @@ -738,7 +738,7 @@ static void read_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha) > { > int i; > void __iomem *address = pm8001_ha->outbnd_q_tbl_addr; > - for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) { > + for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) { > u32 offset = i * 0x24; > pm8001_ha->outbnd_q_tbl[i].ci_pci_bar = > get_pci_bar_index(pm8001_mr32(address, > @@ -758,6 +758,10 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha) > u32 offsetib, offsetob; > void __iomem *addressib = pm8001_ha->inbnd_q_tbl_addr; > void __iomem *addressob = pm8001_ha->outbnd_q_tbl_addr; > + u32 ib_offset = pm8001_ha->ib_offset; > + u32 ob_offset = pm8001_ha->ob_offset; > + u32 ci_offset = pm8001_ha->ci_offset; > + u32 pi_offset = pm8001_ha->pi_offset; > > pm8001_ha->main_cfg_tbl.pm80xx_tbl.upper_event_log_addr = > pm8001_ha->memoryMap.region[AAP1].phys_addr_hi; > @@ -778,23 +782,23 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha) > /* Disable end to end CRC checking */ > pm8001_ha->main_cfg_tbl.pm80xx_tbl.crc_core_dump = (0x1 << 16); > > - for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) { > + for (i = 0; i < pm8001_ha->max_q_num; i++) { > pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt = > PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x00<<30); > pm8001_ha->inbnd_q_tbl[i].upper_base_addr = > - pm8001_ha->memoryMap.region[IB + i].phys_addr_hi; > + pm8001_ha->memoryMap.region[ib_offset + i].phys_addr_hi; > pm8001_ha->inbnd_q_tbl[i].lower_base_addr = > - pm8001_ha->memoryMap.region[IB + i].phys_addr_lo; > + pm8001_ha->memoryMap.region[ib_offset + i].phys_addr_lo; > pm8001_ha->inbnd_q_tbl[i].base_virt = > - (u8 *)pm8001_ha->memoryMap.region[IB + i].virt_ptr; > + (u8 *)pm8001_ha->memoryMap.region[ib_offset + i].virt_ptr; > pm8001_ha->inbnd_q_tbl[i].total_length = > - pm8001_ha->memoryMap.region[IB + i].total_len; > + pm8001_ha->memoryMap.region[ib_offset + i].total_len; > pm8001_ha->inbnd_q_tbl[i].ci_upper_base_addr = > - pm8001_ha->memoryMap.region[CI + i].phys_addr_hi; > + pm8001_ha->memoryMap.region[ci_offset + i].phys_addr_hi; > pm8001_ha->inbnd_q_tbl[i].ci_lower_base_addr = > - pm8001_ha->memoryMap.region[CI + i].phys_addr_lo; > + pm8001_ha->memoryMap.region[ci_offset + i].phys_addr_lo; > pm8001_ha->inbnd_q_tbl[i].ci_virt = > - pm8001_ha->memoryMap.region[CI + i].virt_ptr; > + pm8001_ha->memoryMap.region[ci_offset + i].virt_ptr; > offsetib = i * 0x20; > pm8001_ha->inbnd_q_tbl[i].pi_pci_bar = > get_pci_bar_index(pm8001_mr32(addressib, > @@ -809,25 +813,25 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha) > pm8001_ha->inbnd_q_tbl[i].pi_pci_bar, > pm8001_ha->inbnd_q_tbl[i].pi_offset)); > } > - for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) { > + for (i = 0; i < pm8001_ha->max_q_num; i++) { > pm8001_ha->outbnd_q_tbl[i].element_size_cnt = > PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x01<<30); > pm8001_ha->outbnd_q_tbl[i].upper_base_addr = > - pm8001_ha->memoryMap.region[OB + i].phys_addr_hi; > + pm8001_ha->memoryMap.region[ob_offset + i].phys_addr_hi; > pm8001_ha->outbnd_q_tbl[i].lower_base_addr = > - pm8001_ha->memoryMap.region[OB + i].phys_addr_lo; > + pm8001_ha->memoryMap.region[ob_offset + i].phys_addr_lo; > pm8001_ha->outbnd_q_tbl[i].base_virt = > - (u8 *)pm8001_ha->memoryMap.region[OB + i].virt_ptr; > + (u8 *)pm8001_ha->memoryMap.region[ob_offset + i].virt_ptr; > pm8001_ha->outbnd_q_tbl[i].total_length = > - pm8001_ha->memoryMap.region[OB + i].total_len; > + pm8001_ha->memoryMap.region[ob_offset + i].total_len; > pm8001_ha->outbnd_q_tbl[i].pi_upper_base_addr = > - pm8001_ha->memoryMap.region[PI + i].phys_addr_hi; > + pm8001_ha->memoryMap.region[pi_offset + i].phys_addr_hi; > pm8001_ha->outbnd_q_tbl[i].pi_lower_base_addr = > - pm8001_ha->memoryMap.region[PI + i].phys_addr_lo; > + pm8001_ha->memoryMap.region[pi_offset + i].phys_addr_lo; > /* interrupt vector based on oq */ > pm8001_ha->outbnd_q_tbl[i].interrup_vec_cnt_delay = (i << 24); > pm8001_ha->outbnd_q_tbl[i].pi_virt = > - pm8001_ha->memoryMap.region[PI + i].virt_ptr; > + pm8001_ha->memoryMap.region[pi_offset + i].virt_ptr; > offsetob = i * 0x24; > pm8001_ha->outbnd_q_tbl[i].ci_pci_bar = > get_pci_bar_index(pm8001_mr32(addressob, > @@ -871,7 +875,7 @@ static void update_main_config_table(struct pm8001_hba_info *pm8001_ha) > pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity); > /* Update Fatal error interrupt vector */ > pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt |= > - ((pm8001_ha->number_of_intr - 1) << 8); > + ((pm8001_ha->max_q_num - 1) << 8); > pm8001_mw32(address, MAIN_FATAL_ERROR_INTERRUPT, > pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt); > PM8001_DEV_DBG(pm8001_ha, pm8001_printk( > @@ -1010,8 +1014,12 @@ static int mpi_init_check(struct pm8001_hba_info *pm8001_ha) > value &= SPCv_MSGU_CFG_TABLE_UPDATE; > } while ((value != 0) && (--max_wait_count)); > > - if (!max_wait_count) > - return -1; > + if (!max_wait_count) { > + /* additional check */ > + PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( > + "Inb doorbell clear not toggled[value:%x]\n", value)); > + return -EBUSY; > + } > /* check the MPI-State for initialization upto 100ms*/ > max_wait_count = 100 * 1000;/* 100 msec */ > do { > @@ -1022,12 +1030,12 @@ static int mpi_init_check(struct pm8001_hba_info *pm8001_ha) > } while ((GST_MPI_STATE_INIT != > (gst_len_mpistate & GST_MPI_STATE_MASK)) && (--max_wait_count)); > if (!max_wait_count) > - return -1; > + return -EBUSY; > > /* check MPI Initialization error */ > gst_len_mpistate = gst_len_mpistate >> 16; > if (0x0000 != gst_len_mpistate) > - return -1; > + return -EBUSY; > > return 0; > } > @@ -1469,11 +1477,10 @@ static int pm80xx_chip_init(struct pm8001_hba_info *pm8001_ha) > > /* update main config table ,inbound table and outbound table */ > update_main_config_table(pm8001_ha); > - for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) > + for (i = 0; i < pm8001_ha->max_q_num; i++) { > update_inbnd_queue_table(pm8001_ha, i); > - for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) > update_outbnd_queue_table(pm8001_ha, i); > - > + } > /* notify firmware update finished and check initialization status */ > if (0 == mpi_init_check(pm8001_ha)) { > PM8001_INIT_DBG(pm8001_ha, > @@ -4191,7 +4198,7 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec) > unsigned long flags; > u32 regval; > > - if (vec == (pm8001_ha->number_of_intr - 1)) { > + if (vec == (pm8001_ha->max_q_num - 1)) { > regval = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1); > if ((regval & SCRATCH_PAD_MIPSALL_READY) != > SCRATCH_PAD_MIPSALL_READY) { > @@ -4274,6 +4281,7 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha, > char *preq_dma_addr = NULL; > __le64 tmp_addr; > u32 i, length; > + unsigned long flags; > > memset(&smp_cmd, 0, sizeof(smp_cmd)); > /* > @@ -4369,8 +4377,10 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha, > > build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag, > &smp_cmd, pm8001_ha->smp_exp_mode, length); > + spin_lock_irqsave(&circularQ->iq_lock, flags); > rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &smp_cmd, > sizeof(smp_cmd), 0); > + spin_unlock_irqrestore(&circularQ->iq_lock, flags); > if (rc) > goto err_out_2; > return 0; > @@ -4434,7 +4444,8 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, > u64 phys_addr, start_addr, end_addr; > u32 end_addr_high, end_addr_low; > struct inbound_queue_table *circularQ; > - u32 q_index; > + unsigned long flags; > + u32 q_index, cpu_id; > u32 opc = OPC_INB_SSPINIIOSTART; > memset(&ssp_cmd, 0, sizeof(ssp_cmd)); > memcpy(ssp_cmd.ssp_iu.lun, task->ssp_task.LUN, 8); > @@ -4453,7 +4464,8 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, > ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_attr & 7); > memcpy(ssp_cmd.ssp_iu.cdb, task->ssp_task.cmd->cmnd, > task->ssp_task.cmd->cmd_len); > - q_index = (u32) (pm8001_dev->id & 0x00ffffff) % PM8001_MAX_INB_NUM; > + cpu_id = smp_processor_id(); > + q_index = (u32) (cpu_id) % (pm8001_ha->max_q_num); > circularQ = &pm8001_ha->inbnd_q_tbl[q_index]; > > /* Check if encryption is set */ > @@ -4576,9 +4588,10 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, > ssp_cmd.esgl = 0; > } > } > - q_index = (u32) (pm8001_dev->id & 0x00ffffff) % PM8001_MAX_OUTB_NUM; > + spin_lock_irqsave(&circularQ->iq_lock, flags); > ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, > &ssp_cmd, sizeof(ssp_cmd), q_index); > + spin_unlock_irqrestore(&circularQ->iq_lock, flags); > return ret; > } > > @@ -4590,7 +4603,7 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, > struct pm8001_device *pm8001_ha_dev = dev->lldd_dev; > u32 tag = ccb->ccb_tag; > int ret; > - u32 q_index; > + u32 q_index, cpu_id; > struct sata_start_req sata_cmd; > u32 hdr_tag, ncg_tag = 0; > u64 phys_addr, start_addr, end_addr; > @@ -4601,7 +4614,8 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, > unsigned long flags; > u32 opc = OPC_INB_SATA_HOST_OPSTART; > memset(&sata_cmd, 0, sizeof(sata_cmd)); > - q_index = (u32) (pm8001_ha_dev->id & 0x00ffffff) % PM8001_MAX_INB_NUM; > + cpu_id = smp_processor_id(); > + q_index = (u32) (cpu_id) % (pm8001_ha->max_q_num); > circularQ = &pm8001_ha->inbnd_q_tbl[q_index]; > > if (task->data_dir == DMA_NONE) { > @@ -4817,9 +4831,10 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, > } > } > } > - q_index = (u32) (pm8001_ha_dev->id & 0x00ffffff) % PM8001_MAX_OUTB_NUM; > + spin_lock_irqsave(&circularQ->iq_lock, flags); > ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, > &sata_cmd, sizeof(sata_cmd), q_index); > + spin_unlock_irqrestore(&circularQ->iq_lock, flags); > return ret; > } > > -- > 2.16.3 >
diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c index 77c805db2724..3587f7c8a428 100644 --- a/drivers/scsi/pm8001/pm8001_ctl.c +++ b/drivers/scsi/pm8001/pm8001_ctl.c @@ -408,9 +408,10 @@ static ssize_t pm8001_ctl_ib_queue_log_show(struct device *cdev, int offset; char *str = buf; int start = 0; + u32 ib_offset = pm8001_ha->ib_offset; #define IB_MEMMAP(c) \ (*(u32 *)((u8 *)pm8001_ha-> \ - memoryMap.region[IB].virt_ptr + \ + memoryMap.region[ib_offset].virt_ptr + \ pm8001_ha->evtlog_ib_offset + (c))) for (offset = 0; offset < IB_OB_READ_TIMES; offset++) { @@ -442,9 +443,10 @@ static ssize_t pm8001_ctl_ob_queue_log_show(struct device *cdev, int offset; char *str = buf; int start = 0; + u32 ob_offset = pm8001_ha->ob_offset; #define OB_MEMMAP(c) \ (*(u32 *)((u8 *)pm8001_ha-> \ - memoryMap.region[OB].virt_ptr + \ + memoryMap.region[ob_offset].virt_ptr + \ pm8001_ha->evtlog_ob_offset + (c))) for (offset = 0; offset < IB_OB_READ_TIMES; offset++) { diff --git a/drivers/scsi/pm8001/pm8001_defs.h b/drivers/scsi/pm8001/pm8001_defs.h index 1c7f15fd69ce..a4f52a5a449e 100644 --- a/drivers/scsi/pm8001/pm8001_defs.h +++ b/drivers/scsi/pm8001/pm8001_defs.h @@ -77,10 +77,8 @@ enum port_type { /* driver compile-time configuration */ #define PM8001_MAX_CCB 256 /* max ccbs supported */ #define PM8001_MPI_QUEUE 1024 /* maximum mpi queue entries */ -#define PM8001_MAX_INB_NUM 1 -#define PM8001_MAX_OUTB_NUM 1 -#define PM8001_MAX_SPCV_INB_NUM 1 -#define PM8001_MAX_SPCV_OUTB_NUM 4 +#define PM8001_MAX_INB_NUM 64 +#define PM8001_MAX_OUTB_NUM 64 #define PM8001_CAN_QUEUE 508 /* SCSI Queue depth */ /* Inbound/Outbound queue size */ @@ -94,11 +92,6 @@ enum port_type { #define PM8001_MAX_MSIX_VEC 64 /* max msi-x int for spcv/ve */ #define USI_MAX_MEMCNT_BASE 5 -#define IB (USI_MAX_MEMCNT_BASE + 1) -#define CI (IB + PM8001_MAX_SPCV_INB_NUM) -#define OB (CI + PM8001_MAX_SPCV_INB_NUM) -#define PI (OB + PM8001_MAX_SPCV_OUTB_NUM) -#define USI_MAX_MEMCNT (PI + PM8001_MAX_SPCV_OUTB_NUM) #define CONFIG_SCSI_PM8001_MAX_DMA_SG 528 #define PM8001_MAX_DMA_SG CONFIG_SCSI_PM8001_MAX_DMA_SG enum memory_region_num { @@ -112,6 +105,12 @@ enum memory_region_num { }; #define PM8001_EVENT_LOG_SIZE (128 * 1024) +/** + * maximum DMA memory regions(number of IBQ + number of IBQ CI + * + number of OBQ + number of OBQ PI) + */ +#define USI_MAX_MEMCNT (USI_MAX_MEMCNT_BASE + 1 + ((2 * PM8001_MAX_INB_NUM) \ + + (2 * PM8001_MAX_OUTB_NUM))) /*error code*/ enum mpi_err { MPI_IO_STATUS_SUCCESS = 0x0, diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index e9a939230b15..e9106575a30f 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -189,6 +189,10 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha) u32 offsetib, offsetob; void __iomem *addressib = pm8001_ha->inbnd_q_tbl_addr; void __iomem *addressob = pm8001_ha->outbnd_q_tbl_addr; + u32 ib_offset = pm8001_ha->ib_offset; + u32 ob_offset = pm8001_ha->ob_offset; + u32 ci_offset = pm8001_ha->ci_offset; + u32 pi_offset = pm8001_ha->pi_offset; pm8001_ha->main_cfg_tbl.pm8001_tbl.inbound_q_nppd_hppd = 0; pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_hw_event_pid0_3 = 0; @@ -223,19 +227,19 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha) pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt = PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x00<<30); pm8001_ha->inbnd_q_tbl[i].upper_base_addr = - pm8001_ha->memoryMap.region[IB + i].phys_addr_hi; + pm8001_ha->memoryMap.region[ib_offset + i].phys_addr_hi; pm8001_ha->inbnd_q_tbl[i].lower_base_addr = - pm8001_ha->memoryMap.region[IB + i].phys_addr_lo; + pm8001_ha->memoryMap.region[ib_offset + i].phys_addr_lo; pm8001_ha->inbnd_q_tbl[i].base_virt = - (u8 *)pm8001_ha->memoryMap.region[IB + i].virt_ptr; + (u8 *)pm8001_ha->memoryMap.region[ib_offset + i].virt_ptr; pm8001_ha->inbnd_q_tbl[i].total_length = - pm8001_ha->memoryMap.region[IB + i].total_len; + pm8001_ha->memoryMap.region[ib_offset + i].total_len; pm8001_ha->inbnd_q_tbl[i].ci_upper_base_addr = - pm8001_ha->memoryMap.region[CI + i].phys_addr_hi; + pm8001_ha->memoryMap.region[ci_offset + i].phys_addr_hi; pm8001_ha->inbnd_q_tbl[i].ci_lower_base_addr = - pm8001_ha->memoryMap.region[CI + i].phys_addr_lo; + pm8001_ha->memoryMap.region[ci_offset + i].phys_addr_lo; pm8001_ha->inbnd_q_tbl[i].ci_virt = - pm8001_ha->memoryMap.region[CI + i].virt_ptr; + pm8001_ha->memoryMap.region[ci_offset + i].virt_ptr; offsetib = i * 0x20; pm8001_ha->inbnd_q_tbl[i].pi_pci_bar = get_pci_bar_index(pm8001_mr32(addressib, @@ -249,21 +253,21 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha) pm8001_ha->outbnd_q_tbl[i].element_size_cnt = PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x01<<30); pm8001_ha->outbnd_q_tbl[i].upper_base_addr = - pm8001_ha->memoryMap.region[OB + i].phys_addr_hi; + pm8001_ha->memoryMap.region[ob_offset + i].phys_addr_hi; pm8001_ha->outbnd_q_tbl[i].lower_base_addr = - pm8001_ha->memoryMap.region[OB + i].phys_addr_lo; + pm8001_ha->memoryMap.region[ob_offset + i].phys_addr_lo; pm8001_ha->outbnd_q_tbl[i].base_virt = - (u8 *)pm8001_ha->memoryMap.region[OB + i].virt_ptr; + (u8 *)pm8001_ha->memoryMap.region[ob_offset + i].virt_ptr; pm8001_ha->outbnd_q_tbl[i].total_length = - pm8001_ha->memoryMap.region[OB + i].total_len; + pm8001_ha->memoryMap.region[ob_offset + i].total_len; pm8001_ha->outbnd_q_tbl[i].pi_upper_base_addr = - pm8001_ha->memoryMap.region[PI + i].phys_addr_hi; + pm8001_ha->memoryMap.region[pi_offset + i].phys_addr_hi; pm8001_ha->outbnd_q_tbl[i].pi_lower_base_addr = - pm8001_ha->memoryMap.region[PI + i].phys_addr_lo; + pm8001_ha->memoryMap.region[pi_offset + i].phys_addr_lo; pm8001_ha->outbnd_q_tbl[i].interrup_vec_cnt_delay = 0 | (10 << 16) | (i << 24); pm8001_ha->outbnd_q_tbl[i].pi_virt = - pm8001_ha->memoryMap.region[PI + i].virt_ptr; + pm8001_ha->memoryMap.region[pi_offset + i].virt_ptr; offsetob = i * 0x24; pm8001_ha->outbnd_q_tbl[i].ci_pci_bar = get_pci_bar_index(pm8001_mr32(addressob, diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 20fa96cbc9d3..c744f846e08d 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -264,12 +264,36 @@ static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha); static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, const struct pci_device_id *ent) { - int i; + int i, count = 0, rc = 0; + u32 ci_offset, ib_offset, ob_offset, pi_offset; + struct inbound_queue_table *circularQ; + 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)); + + /* Setup Interrupt */ + rc = pm8001_setup_irq(pm8001_ha); + if (rc) { + PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( + "pm8001_setup_irq failed [ret: %d]\n", rc)); + goto err_out_shost; + } + /* Request Interrupt */ + rc = pm8001_request_irq(pm8001_ha); + if (rc) + goto err_out_shost; + + count = pm8001_ha->max_q_num; + /* Queues are chosen based on the number of cores/msix availability */ + ib_offset = pm8001_ha->ib_offset = USI_MAX_MEMCNT_BASE + 1; + ci_offset = pm8001_ha->ci_offset = ib_offset + count; + ob_offset = pm8001_ha->ob_offset = ci_offset + count; + pi_offset = pm8001_ha->pi_offset = ob_offset + count; + pm8001_ha->max_memcnt = pi_offset + count; + for (i = 0; i < pm8001_ha->chip->n_phy; i++) { pm8001_phy_init(pm8001_ha, i); pm8001_ha->port[i].wide_port_phymap = 0; @@ -293,54 +317,62 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, pm8001_ha->memoryMap.region[IOP].total_len = PM8001_EVENT_LOG_SIZE; pm8001_ha->memoryMap.region[IOP].alignment = 32; - for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) { + for (i = 0; i < count; i++) { + circularQ = &pm8001_ha->inbnd_q_tbl[i]; + spin_lock_init(&circularQ->iq_lock); /* MPI Memory region 3 for consumer Index of inbound queues */ - pm8001_ha->memoryMap.region[CI+i].num_elements = 1; - pm8001_ha->memoryMap.region[CI+i].element_size = 4; - pm8001_ha->memoryMap.region[CI+i].total_len = 4; - pm8001_ha->memoryMap.region[CI+i].alignment = 4; + pm8001_ha->memoryMap.region[ci_offset+i].num_elements = 1; + pm8001_ha->memoryMap.region[ci_offset+i].element_size = 4; + pm8001_ha->memoryMap.region[ci_offset+i].total_len = 4; + pm8001_ha->memoryMap.region[ci_offset+i].alignment = 4; if ((ent->driver_data) != chip_8001) { /* MPI Memory region 5 inbound queues */ - pm8001_ha->memoryMap.region[IB+i].num_elements = + pm8001_ha->memoryMap.region[ib_offset+i].num_elements = PM8001_MPI_QUEUE; - pm8001_ha->memoryMap.region[IB+i].element_size = 128; - pm8001_ha->memoryMap.region[IB+i].total_len = + pm8001_ha->memoryMap.region[ib_offset+i].element_size + = 128; + pm8001_ha->memoryMap.region[ib_offset+i].total_len = PM8001_MPI_QUEUE * 128; - pm8001_ha->memoryMap.region[IB+i].alignment = 128; + pm8001_ha->memoryMap.region[ib_offset+i].alignment + = 128; } else { - pm8001_ha->memoryMap.region[IB+i].num_elements = + pm8001_ha->memoryMap.region[ib_offset+i].num_elements = PM8001_MPI_QUEUE; - pm8001_ha->memoryMap.region[IB+i].element_size = 64; - pm8001_ha->memoryMap.region[IB+i].total_len = + pm8001_ha->memoryMap.region[ib_offset+i].element_size + = 64; + pm8001_ha->memoryMap.region[ib_offset+i].total_len = PM8001_MPI_QUEUE * 64; - pm8001_ha->memoryMap.region[IB+i].alignment = 64; + pm8001_ha->memoryMap.region[ib_offset+i].alignment = 64; } } - for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) { + for (i = 0; i < count; i++) { /* MPI Memory region 4 for producer Index of outbound queues */ - pm8001_ha->memoryMap.region[PI+i].num_elements = 1; - pm8001_ha->memoryMap.region[PI+i].element_size = 4; - pm8001_ha->memoryMap.region[PI+i].total_len = 4; - pm8001_ha->memoryMap.region[PI+i].alignment = 4; + pm8001_ha->memoryMap.region[pi_offset+i].num_elements = 1; + pm8001_ha->memoryMap.region[pi_offset+i].element_size = 4; + pm8001_ha->memoryMap.region[pi_offset+i].total_len = 4; + pm8001_ha->memoryMap.region[pi_offset+i].alignment = 4; if (ent->driver_data != chip_8001) { /* MPI Memory region 6 Outbound queues */ - pm8001_ha->memoryMap.region[OB+i].num_elements = + pm8001_ha->memoryMap.region[ob_offset+i].num_elements = PM8001_MPI_QUEUE; - pm8001_ha->memoryMap.region[OB+i].element_size = 128; - pm8001_ha->memoryMap.region[OB+i].total_len = + pm8001_ha->memoryMap.region[ob_offset+i].element_size + = 128; + pm8001_ha->memoryMap.region[ob_offset+i].total_len = PM8001_MPI_QUEUE * 128; - pm8001_ha->memoryMap.region[OB+i].alignment = 128; + pm8001_ha->memoryMap.region[ob_offset+i].alignment + = 128; } else { /* MPI Memory region 6 Outbound queues */ - pm8001_ha->memoryMap.region[OB+i].num_elements = + pm8001_ha->memoryMap.region[ob_offset+i].num_elements = PM8001_MPI_QUEUE; - pm8001_ha->memoryMap.region[OB+i].element_size = 64; - pm8001_ha->memoryMap.region[OB+i].total_len = + pm8001_ha->memoryMap.region[ob_offset+i].element_size + = 64; + pm8001_ha->memoryMap.region[ob_offset+i].total_len = PM8001_MPI_QUEUE * 64; - pm8001_ha->memoryMap.region[OB+i].alignment = 64; + pm8001_ha->memoryMap.region[ob_offset+i].alignment = 64; } } @@ -369,7 +401,7 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, pm8001_ha->memoryMap.region[FORENSIC_MEM].total_len = 0x10000; pm8001_ha->memoryMap.region[FORENSIC_MEM].element_size = 0x10000; pm8001_ha->memoryMap.region[FORENSIC_MEM].alignment = 0x10000; - for (i = 0; i < USI_MAX_MEMCNT; i++) { + for (i = 0; i < pm8001_ha->max_memcnt; i++) { if (pm8001_mem_alloc(pm8001_ha->pdev, &pm8001_ha->memoryMap.region[i].virt_ptr, &pm8001_ha->memoryMap.region[i].phys_addr, @@ -405,6 +437,8 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, /* Initialize tags */ pm8001_tag_init(pm8001_ha); return 0; +err_out_shost: + scsi_remove_host(pm8001_ha->shost); err_out: return 1; } @@ -899,7 +933,8 @@ static int pm8001_configure_phy_settings(struct pm8001_hba_info *pm8001_ha) static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha) { u32 number_of_intr; - int rc; + int rc, cpu_online_count; + unsigned int allocated_irq_vectors; /* SPCv controllers supports 64 msi-x */ if (pm8001_ha->chip_id == chip_8001) { @@ -908,13 +943,21 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha) number_of_intr = PM8001_MAX_MSIX_VEC; } + cpu_online_count = num_online_cpus(); + number_of_intr = min_t(int, cpu_online_count, number_of_intr); rc = pci_alloc_irq_vectors(pm8001_ha->pdev, number_of_intr, number_of_intr, PCI_IRQ_MSIX); - number_of_intr = rc; + allocated_irq_vectors = rc; if (rc < 0) return rc; + + /*Assigns the number of interrupts */ + number_of_intr = min_t(int, allocated_irq_vectors, number_of_intr); pm8001_ha->number_of_intr = number_of_intr; + /*maximum queue number updating in HBA structure */ + pm8001_ha->max_q_num = number_of_intr; + PM8001_INIT_DBG(pm8001_ha, pm8001_printk( "pci_alloc_irq_vectors request ret:%d no of intr %d\n", rc, pm8001_ha->number_of_intr)); @@ -1069,13 +1112,6 @@ static int pm8001_pci_probe(struct pci_dev *pdev, rc = -ENOMEM; goto err_out_free; } - /* Setup Interrupt */ - rc = pm8001_setup_irq(pm8001_ha); - if (rc) { - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( - "pm8001_setup_irq failed [ret: %d]\n", rc)); - goto err_out_shost; - } PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha); rc = PM8001_CHIP_DISP->chip_init(pm8001_ha); @@ -1088,13 +1124,6 @@ static int pm8001_pci_probe(struct pci_dev *pdev, rc = scsi_add_host(shost, &pdev->dev); if (rc) goto err_out_ha_free; - /* Request Interrupt */ - rc = pm8001_request_irq(pm8001_ha); - if (rc) { - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( - "pm8001_request_irq failed [ret: %d]\n", rc)); - goto err_out_shost; - } PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0); if (pm8001_ha->chip_id != chip_8001) { diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index ae7ba9b3c4bc..bdfce3c3f619 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h @@ -468,6 +468,7 @@ struct inbound_queue_table { u32 reserved; __le32 consumer_index; u32 producer_idx; + spinlock_t iq_lock; }; struct outbound_queue_table { u32 element_size_cnt; @@ -524,8 +525,8 @@ struct pm8001_hba_info { void __iomem *fatal_tbl_addr; /*MPI IVT Table Addr */ union main_cfg_table main_cfg_tbl; union general_status_table gs_tbl; - struct inbound_queue_table inbnd_q_tbl[PM8001_MAX_SPCV_INB_NUM]; - struct outbound_queue_table outbnd_q_tbl[PM8001_MAX_SPCV_OUTB_NUM]; + struct inbound_queue_table inbnd_q_tbl[PM8001_MAX_INB_NUM]; + struct outbound_queue_table outbnd_q_tbl[PM8001_MAX_OUTB_NUM]; struct sas_phy_attribute_table phy_attr_table; /* MPI SAS PHY attributes */ u8 sas_addr[SAS_ADDR_SIZE]; @@ -561,6 +562,12 @@ struct pm8001_hba_info { u32 reset_in_progress; u32 non_fatal_count; u32 non_fatal_read_length; + u32 max_q_num; + u32 ib_offset; + u32 ob_offset; + u32 ci_offset; + u32 pi_offset; + u32 max_memcnt; }; struct pm8001_work { diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index b42f41d1ed49..26e9e8877107 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c @@ -720,7 +720,7 @@ static void read_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha) { int i; void __iomem *address = pm8001_ha->inbnd_q_tbl_addr; - for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) { + for (i = 0; i < PM8001_MAX_INB_NUM; i++) { u32 offset = i * 0x20; pm8001_ha->inbnd_q_tbl[i].pi_pci_bar = get_pci_bar_index(pm8001_mr32(address, @@ -738,7 +738,7 @@ static void read_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha) { int i; void __iomem *address = pm8001_ha->outbnd_q_tbl_addr; - for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) { + for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) { u32 offset = i * 0x24; pm8001_ha->outbnd_q_tbl[i].ci_pci_bar = get_pci_bar_index(pm8001_mr32(address, @@ -758,6 +758,10 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha) u32 offsetib, offsetob; void __iomem *addressib = pm8001_ha->inbnd_q_tbl_addr; void __iomem *addressob = pm8001_ha->outbnd_q_tbl_addr; + u32 ib_offset = pm8001_ha->ib_offset; + u32 ob_offset = pm8001_ha->ob_offset; + u32 ci_offset = pm8001_ha->ci_offset; + u32 pi_offset = pm8001_ha->pi_offset; pm8001_ha->main_cfg_tbl.pm80xx_tbl.upper_event_log_addr = pm8001_ha->memoryMap.region[AAP1].phys_addr_hi; @@ -778,23 +782,23 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha) /* Disable end to end CRC checking */ pm8001_ha->main_cfg_tbl.pm80xx_tbl.crc_core_dump = (0x1 << 16); - for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) { + for (i = 0; i < pm8001_ha->max_q_num; i++) { pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt = PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x00<<30); pm8001_ha->inbnd_q_tbl[i].upper_base_addr = - pm8001_ha->memoryMap.region[IB + i].phys_addr_hi; + pm8001_ha->memoryMap.region[ib_offset + i].phys_addr_hi; pm8001_ha->inbnd_q_tbl[i].lower_base_addr = - pm8001_ha->memoryMap.region[IB + i].phys_addr_lo; + pm8001_ha->memoryMap.region[ib_offset + i].phys_addr_lo; pm8001_ha->inbnd_q_tbl[i].base_virt = - (u8 *)pm8001_ha->memoryMap.region[IB + i].virt_ptr; + (u8 *)pm8001_ha->memoryMap.region[ib_offset + i].virt_ptr; pm8001_ha->inbnd_q_tbl[i].total_length = - pm8001_ha->memoryMap.region[IB + i].total_len; + pm8001_ha->memoryMap.region[ib_offset + i].total_len; pm8001_ha->inbnd_q_tbl[i].ci_upper_base_addr = - pm8001_ha->memoryMap.region[CI + i].phys_addr_hi; + pm8001_ha->memoryMap.region[ci_offset + i].phys_addr_hi; pm8001_ha->inbnd_q_tbl[i].ci_lower_base_addr = - pm8001_ha->memoryMap.region[CI + i].phys_addr_lo; + pm8001_ha->memoryMap.region[ci_offset + i].phys_addr_lo; pm8001_ha->inbnd_q_tbl[i].ci_virt = - pm8001_ha->memoryMap.region[CI + i].virt_ptr; + pm8001_ha->memoryMap.region[ci_offset + i].virt_ptr; offsetib = i * 0x20; pm8001_ha->inbnd_q_tbl[i].pi_pci_bar = get_pci_bar_index(pm8001_mr32(addressib, @@ -809,25 +813,25 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha) pm8001_ha->inbnd_q_tbl[i].pi_pci_bar, pm8001_ha->inbnd_q_tbl[i].pi_offset)); } - for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) { + for (i = 0; i < pm8001_ha->max_q_num; i++) { pm8001_ha->outbnd_q_tbl[i].element_size_cnt = PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x01<<30); pm8001_ha->outbnd_q_tbl[i].upper_base_addr = - pm8001_ha->memoryMap.region[OB + i].phys_addr_hi; + pm8001_ha->memoryMap.region[ob_offset + i].phys_addr_hi; pm8001_ha->outbnd_q_tbl[i].lower_base_addr = - pm8001_ha->memoryMap.region[OB + i].phys_addr_lo; + pm8001_ha->memoryMap.region[ob_offset + i].phys_addr_lo; pm8001_ha->outbnd_q_tbl[i].base_virt = - (u8 *)pm8001_ha->memoryMap.region[OB + i].virt_ptr; + (u8 *)pm8001_ha->memoryMap.region[ob_offset + i].virt_ptr; pm8001_ha->outbnd_q_tbl[i].total_length = - pm8001_ha->memoryMap.region[OB + i].total_len; + pm8001_ha->memoryMap.region[ob_offset + i].total_len; pm8001_ha->outbnd_q_tbl[i].pi_upper_base_addr = - pm8001_ha->memoryMap.region[PI + i].phys_addr_hi; + pm8001_ha->memoryMap.region[pi_offset + i].phys_addr_hi; pm8001_ha->outbnd_q_tbl[i].pi_lower_base_addr = - pm8001_ha->memoryMap.region[PI + i].phys_addr_lo; + pm8001_ha->memoryMap.region[pi_offset + i].phys_addr_lo; /* interrupt vector based on oq */ pm8001_ha->outbnd_q_tbl[i].interrup_vec_cnt_delay = (i << 24); pm8001_ha->outbnd_q_tbl[i].pi_virt = - pm8001_ha->memoryMap.region[PI + i].virt_ptr; + pm8001_ha->memoryMap.region[pi_offset + i].virt_ptr; offsetob = i * 0x24; pm8001_ha->outbnd_q_tbl[i].ci_pci_bar = get_pci_bar_index(pm8001_mr32(addressob, @@ -871,7 +875,7 @@ static void update_main_config_table(struct pm8001_hba_info *pm8001_ha) pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity); /* Update Fatal error interrupt vector */ pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt |= - ((pm8001_ha->number_of_intr - 1) << 8); + ((pm8001_ha->max_q_num - 1) << 8); pm8001_mw32(address, MAIN_FATAL_ERROR_INTERRUPT, pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt); PM8001_DEV_DBG(pm8001_ha, pm8001_printk( @@ -1010,8 +1014,12 @@ static int mpi_init_check(struct pm8001_hba_info *pm8001_ha) value &= SPCv_MSGU_CFG_TABLE_UPDATE; } while ((value != 0) && (--max_wait_count)); - if (!max_wait_count) - return -1; + if (!max_wait_count) { + /* additional check */ + PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( + "Inb doorbell clear not toggled[value:%x]\n", value)); + return -EBUSY; + } /* check the MPI-State for initialization upto 100ms*/ max_wait_count = 100 * 1000;/* 100 msec */ do { @@ -1022,12 +1030,12 @@ static int mpi_init_check(struct pm8001_hba_info *pm8001_ha) } while ((GST_MPI_STATE_INIT != (gst_len_mpistate & GST_MPI_STATE_MASK)) && (--max_wait_count)); if (!max_wait_count) - return -1; + return -EBUSY; /* check MPI Initialization error */ gst_len_mpistate = gst_len_mpistate >> 16; if (0x0000 != gst_len_mpistate) - return -1; + return -EBUSY; return 0; } @@ -1469,11 +1477,10 @@ static int pm80xx_chip_init(struct pm8001_hba_info *pm8001_ha) /* update main config table ,inbound table and outbound table */ update_main_config_table(pm8001_ha); - for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) + for (i = 0; i < pm8001_ha->max_q_num; i++) { update_inbnd_queue_table(pm8001_ha, i); - for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) update_outbnd_queue_table(pm8001_ha, i); - + } /* notify firmware update finished and check initialization status */ if (0 == mpi_init_check(pm8001_ha)) { PM8001_INIT_DBG(pm8001_ha, @@ -4191,7 +4198,7 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec) unsigned long flags; u32 regval; - if (vec == (pm8001_ha->number_of_intr - 1)) { + if (vec == (pm8001_ha->max_q_num - 1)) { regval = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1); if ((regval & SCRATCH_PAD_MIPSALL_READY) != SCRATCH_PAD_MIPSALL_READY) { @@ -4274,6 +4281,7 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha, char *preq_dma_addr = NULL; __le64 tmp_addr; u32 i, length; + unsigned long flags; memset(&smp_cmd, 0, sizeof(smp_cmd)); /* @@ -4369,8 +4377,10 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha, build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag, &smp_cmd, pm8001_ha->smp_exp_mode, length); + spin_lock_irqsave(&circularQ->iq_lock, flags); rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &smp_cmd, sizeof(smp_cmd), 0); + spin_unlock_irqrestore(&circularQ->iq_lock, flags); if (rc) goto err_out_2; return 0; @@ -4434,7 +4444,8 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, u64 phys_addr, start_addr, end_addr; u32 end_addr_high, end_addr_low; struct inbound_queue_table *circularQ; - u32 q_index; + unsigned long flags; + u32 q_index, cpu_id; u32 opc = OPC_INB_SSPINIIOSTART; memset(&ssp_cmd, 0, sizeof(ssp_cmd)); memcpy(ssp_cmd.ssp_iu.lun, task->ssp_task.LUN, 8); @@ -4453,7 +4464,8 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_attr & 7); memcpy(ssp_cmd.ssp_iu.cdb, task->ssp_task.cmd->cmnd, task->ssp_task.cmd->cmd_len); - q_index = (u32) (pm8001_dev->id & 0x00ffffff) % PM8001_MAX_INB_NUM; + cpu_id = smp_processor_id(); + q_index = (u32) (cpu_id) % (pm8001_ha->max_q_num); circularQ = &pm8001_ha->inbnd_q_tbl[q_index]; /* Check if encryption is set */ @@ -4576,9 +4588,10 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, ssp_cmd.esgl = 0; } } - q_index = (u32) (pm8001_dev->id & 0x00ffffff) % PM8001_MAX_OUTB_NUM; + spin_lock_irqsave(&circularQ->iq_lock, flags); ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &ssp_cmd, sizeof(ssp_cmd), q_index); + spin_unlock_irqrestore(&circularQ->iq_lock, flags); return ret; } @@ -4590,7 +4603,7 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, struct pm8001_device *pm8001_ha_dev = dev->lldd_dev; u32 tag = ccb->ccb_tag; int ret; - u32 q_index; + u32 q_index, cpu_id; struct sata_start_req sata_cmd; u32 hdr_tag, ncg_tag = 0; u64 phys_addr, start_addr, end_addr; @@ -4601,7 +4614,8 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, unsigned long flags; u32 opc = OPC_INB_SATA_HOST_OPSTART; memset(&sata_cmd, 0, sizeof(sata_cmd)); - q_index = (u32) (pm8001_ha_dev->id & 0x00ffffff) % PM8001_MAX_INB_NUM; + cpu_id = smp_processor_id(); + q_index = (u32) (cpu_id) % (pm8001_ha->max_q_num); circularQ = &pm8001_ha->inbnd_q_tbl[q_index]; if (task->data_dir == DMA_NONE) { @@ -4817,9 +4831,10 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, } } } - q_index = (u32) (pm8001_ha_dev->id & 0x00ffffff) % PM8001_MAX_OUTB_NUM; + spin_lock_irqsave(&circularQ->iq_lock, flags); ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, sizeof(sata_cmd), q_index); + spin_unlock_irqrestore(&circularQ->iq_lock, flags); return ret; }