Skip to content

Commit 05c6c02

Browse files
Viswas Gmartinkpetersen
authored andcommitted
scsi: pm80xx: Increase number of supported queues
Current driver uses fixed number of Inbound and Outbound queues and all of the I/O, TMF and internal requests are submitted through those. A global spin lock is used to control the shared access. This can create a lock contention and it is real bottleneck in the I/O path. To avoid this, the number of supported Inbound and Outbound queues is increased to 64, and the number of queues used is decided based on number of CPU cores online and number of MSI-X vectors allocated. Also add locks per queue instead of using the global lock. Link: https://lore.kernel.org/r/20201005145011.23674-2-Viswas.G@microchip.com.com Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com> Signed-off-by: Viswas G <Viswas.G@microchip.com> Signed-off-by: Ruksar Devadi <Ruksar.devadi@microchip.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 1725ba8 commit 05c6c02

File tree

6 files changed

+160
-104
lines changed

6 files changed

+160
-104
lines changed

drivers/scsi/pm8001/pm8001_ctl.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -408,9 +408,10 @@ static ssize_t pm8001_ctl_ib_queue_log_show(struct device *cdev,
408408
int offset;
409409
char *str = buf;
410410
int start = 0;
411+
u32 ib_offset = pm8001_ha->ib_offset;
411412
#define IB_MEMMAP(c) \
412413
(*(u32 *)((u8 *)pm8001_ha-> \
413-
memoryMap.region[IB].virt_ptr + \
414+
memoryMap.region[ib_offset].virt_ptr + \
414415
pm8001_ha->evtlog_ib_offset + (c)))
415416

416417
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,
442443
int offset;
443444
char *str = buf;
444445
int start = 0;
446+
u32 ob_offset = pm8001_ha->ob_offset;
445447
#define OB_MEMMAP(c) \
446448
(*(u32 *)((u8 *)pm8001_ha-> \
447-
memoryMap.region[OB].virt_ptr + \
449+
memoryMap.region[ob_offset].virt_ptr + \
448450
pm8001_ha->evtlog_ob_offset + (c)))
449451

450452
for (offset = 0; offset < IB_OB_READ_TIMES; offset++) {

drivers/scsi/pm8001/pm8001_defs.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,8 @@ enum port_type {
7777
/* driver compile-time configuration */
7878
#define PM8001_MAX_CCB 256 /* max ccbs supported */
7979
#define PM8001_MPI_QUEUE 1024 /* maximum mpi queue entries */
80-
#define PM8001_MAX_INB_NUM 1
81-
#define PM8001_MAX_OUTB_NUM 1
82-
#define PM8001_MAX_SPCV_INB_NUM 1
83-
#define PM8001_MAX_SPCV_OUTB_NUM 4
80+
#define PM8001_MAX_INB_NUM 64
81+
#define PM8001_MAX_OUTB_NUM 64
8482
#define PM8001_CAN_QUEUE 508 /* SCSI Queue depth */
8583

8684
/* Inbound/Outbound queue size */
@@ -94,11 +92,6 @@ enum port_type {
9492
#define PM8001_MAX_MSIX_VEC 64 /* max msi-x int for spcv/ve */
9593

9694
#define USI_MAX_MEMCNT_BASE 5
97-
#define IB (USI_MAX_MEMCNT_BASE + 1)
98-
#define CI (IB + PM8001_MAX_SPCV_INB_NUM)
99-
#define OB (CI + PM8001_MAX_SPCV_INB_NUM)
100-
#define PI (OB + PM8001_MAX_SPCV_OUTB_NUM)
101-
#define USI_MAX_MEMCNT (PI + PM8001_MAX_SPCV_OUTB_NUM)
10295
#define CONFIG_SCSI_PM8001_MAX_DMA_SG 528
10396
#define PM8001_MAX_DMA_SG CONFIG_SCSI_PM8001_MAX_DMA_SG
10497
enum memory_region_num {
@@ -112,6 +105,12 @@ enum memory_region_num {
112105
};
113106
#define PM8001_EVENT_LOG_SIZE (128 * 1024)
114107

108+
/**
109+
* maximum DMA memory regions(number of IBQ + number of IBQ CI
110+
* + number of OBQ + number of OBQ PI)
111+
*/
112+
#define USI_MAX_MEMCNT (USI_MAX_MEMCNT_BASE + 1 + ((2 * PM8001_MAX_INB_NUM) \
113+
+ (2 * PM8001_MAX_OUTB_NUM)))
115114
/*error code*/
116115
enum mpi_err {
117116
MPI_IO_STATUS_SUCCESS = 0x0,

drivers/scsi/pm8001/pm8001_hwi.c

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,10 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
189189
u32 offsetib, offsetob;
190190
void __iomem *addressib = pm8001_ha->inbnd_q_tbl_addr;
191191
void __iomem *addressob = pm8001_ha->outbnd_q_tbl_addr;
192+
u32 ib_offset = pm8001_ha->ib_offset;
193+
u32 ob_offset = pm8001_ha->ob_offset;
194+
u32 ci_offset = pm8001_ha->ci_offset;
195+
u32 pi_offset = pm8001_ha->pi_offset;
192196

193197
pm8001_ha->main_cfg_tbl.pm8001_tbl.inbound_q_nppd_hppd = 0;
194198
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)
223227
pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt =
224228
PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x00<<30);
225229
pm8001_ha->inbnd_q_tbl[i].upper_base_addr =
226-
pm8001_ha->memoryMap.region[IB + i].phys_addr_hi;
230+
pm8001_ha->memoryMap.region[ib_offset + i].phys_addr_hi;
227231
pm8001_ha->inbnd_q_tbl[i].lower_base_addr =
228-
pm8001_ha->memoryMap.region[IB + i].phys_addr_lo;
232+
pm8001_ha->memoryMap.region[ib_offset + i].phys_addr_lo;
229233
pm8001_ha->inbnd_q_tbl[i].base_virt =
230-
(u8 *)pm8001_ha->memoryMap.region[IB + i].virt_ptr;
234+
(u8 *)pm8001_ha->memoryMap.region[ib_offset + i].virt_ptr;
231235
pm8001_ha->inbnd_q_tbl[i].total_length =
232-
pm8001_ha->memoryMap.region[IB + i].total_len;
236+
pm8001_ha->memoryMap.region[ib_offset + i].total_len;
233237
pm8001_ha->inbnd_q_tbl[i].ci_upper_base_addr =
234-
pm8001_ha->memoryMap.region[CI + i].phys_addr_hi;
238+
pm8001_ha->memoryMap.region[ci_offset + i].phys_addr_hi;
235239
pm8001_ha->inbnd_q_tbl[i].ci_lower_base_addr =
236-
pm8001_ha->memoryMap.region[CI + i].phys_addr_lo;
240+
pm8001_ha->memoryMap.region[ci_offset + i].phys_addr_lo;
237241
pm8001_ha->inbnd_q_tbl[i].ci_virt =
238-
pm8001_ha->memoryMap.region[CI + i].virt_ptr;
242+
pm8001_ha->memoryMap.region[ci_offset + i].virt_ptr;
239243
offsetib = i * 0x20;
240244
pm8001_ha->inbnd_q_tbl[i].pi_pci_bar =
241245
get_pci_bar_index(pm8001_mr32(addressib,
@@ -249,21 +253,21 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
249253
pm8001_ha->outbnd_q_tbl[i].element_size_cnt =
250254
PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x01<<30);
251255
pm8001_ha->outbnd_q_tbl[i].upper_base_addr =
252-
pm8001_ha->memoryMap.region[OB + i].phys_addr_hi;
256+
pm8001_ha->memoryMap.region[ob_offset + i].phys_addr_hi;
253257
pm8001_ha->outbnd_q_tbl[i].lower_base_addr =
254-
pm8001_ha->memoryMap.region[OB + i].phys_addr_lo;
258+
pm8001_ha->memoryMap.region[ob_offset + i].phys_addr_lo;
255259
pm8001_ha->outbnd_q_tbl[i].base_virt =
256-
(u8 *)pm8001_ha->memoryMap.region[OB + i].virt_ptr;
260+
(u8 *)pm8001_ha->memoryMap.region[ob_offset + i].virt_ptr;
257261
pm8001_ha->outbnd_q_tbl[i].total_length =
258-
pm8001_ha->memoryMap.region[OB + i].total_len;
262+
pm8001_ha->memoryMap.region[ob_offset + i].total_len;
259263
pm8001_ha->outbnd_q_tbl[i].pi_upper_base_addr =
260-
pm8001_ha->memoryMap.region[PI + i].phys_addr_hi;
264+
pm8001_ha->memoryMap.region[pi_offset + i].phys_addr_hi;
261265
pm8001_ha->outbnd_q_tbl[i].pi_lower_base_addr =
262-
pm8001_ha->memoryMap.region[PI + i].phys_addr_lo;
266+
pm8001_ha->memoryMap.region[pi_offset + i].phys_addr_lo;
263267
pm8001_ha->outbnd_q_tbl[i].interrup_vec_cnt_delay =
264268
0 | (10 << 16) | (i << 24);
265269
pm8001_ha->outbnd_q_tbl[i].pi_virt =
266-
pm8001_ha->memoryMap.region[PI + i].virt_ptr;
270+
pm8001_ha->memoryMap.region[pi_offset + i].virt_ptr;
267271
offsetob = i * 0x24;
268272
pm8001_ha->outbnd_q_tbl[i].ci_pci_bar =
269273
get_pci_bar_index(pm8001_mr32(addressob,

drivers/scsi/pm8001/pm8001_init.c

Lines changed: 73 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -264,12 +264,36 @@ static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha);
264264
static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha,
265265
const struct pci_device_id *ent)
266266
{
267-
int i;
267+
int i, count = 0, rc = 0;
268+
u32 ci_offset, ib_offset, ob_offset, pi_offset;
269+
struct inbound_queue_table *circularQ;
270+
268271
spin_lock_init(&pm8001_ha->lock);
269272
spin_lock_init(&pm8001_ha->bitmap_lock);
270273
PM8001_INIT_DBG(pm8001_ha,
271274
pm8001_printk("pm8001_alloc: PHY:%x\n",
272275
pm8001_ha->chip->n_phy));
276+
277+
/* Setup Interrupt */
278+
rc = pm8001_setup_irq(pm8001_ha);
279+
if (rc) {
280+
PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
281+
"pm8001_setup_irq failed [ret: %d]\n", rc));
282+
goto err_out_shost;
283+
}
284+
/* Request Interrupt */
285+
rc = pm8001_request_irq(pm8001_ha);
286+
if (rc)
287+
goto err_out_shost;
288+
289+
count = pm8001_ha->max_q_num;
290+
/* Queues are chosen based on the number of cores/msix availability */
291+
ib_offset = pm8001_ha->ib_offset = USI_MAX_MEMCNT_BASE + 1;
292+
ci_offset = pm8001_ha->ci_offset = ib_offset + count;
293+
ob_offset = pm8001_ha->ob_offset = ci_offset + count;
294+
pi_offset = pm8001_ha->pi_offset = ob_offset + count;
295+
pm8001_ha->max_memcnt = pi_offset + count;
296+
273297
for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
274298
pm8001_phy_init(pm8001_ha, i);
275299
pm8001_ha->port[i].wide_port_phymap = 0;
@@ -293,54 +317,62 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha,
293317
pm8001_ha->memoryMap.region[IOP].total_len = PM8001_EVENT_LOG_SIZE;
294318
pm8001_ha->memoryMap.region[IOP].alignment = 32;
295319

296-
for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) {
320+
for (i = 0; i < count; i++) {
321+
circularQ = &pm8001_ha->inbnd_q_tbl[i];
322+
spin_lock_init(&circularQ->iq_lock);
297323
/* MPI Memory region 3 for consumer Index of inbound queues */
298-
pm8001_ha->memoryMap.region[CI+i].num_elements = 1;
299-
pm8001_ha->memoryMap.region[CI+i].element_size = 4;
300-
pm8001_ha->memoryMap.region[CI+i].total_len = 4;
301-
pm8001_ha->memoryMap.region[CI+i].alignment = 4;
324+
pm8001_ha->memoryMap.region[ci_offset+i].num_elements = 1;
325+
pm8001_ha->memoryMap.region[ci_offset+i].element_size = 4;
326+
pm8001_ha->memoryMap.region[ci_offset+i].total_len = 4;
327+
pm8001_ha->memoryMap.region[ci_offset+i].alignment = 4;
302328

303329
if ((ent->driver_data) != chip_8001) {
304330
/* MPI Memory region 5 inbound queues */
305-
pm8001_ha->memoryMap.region[IB+i].num_elements =
331+
pm8001_ha->memoryMap.region[ib_offset+i].num_elements =
306332
PM8001_MPI_QUEUE;
307-
pm8001_ha->memoryMap.region[IB+i].element_size = 128;
308-
pm8001_ha->memoryMap.region[IB+i].total_len =
333+
pm8001_ha->memoryMap.region[ib_offset+i].element_size
334+
= 128;
335+
pm8001_ha->memoryMap.region[ib_offset+i].total_len =
309336
PM8001_MPI_QUEUE * 128;
310-
pm8001_ha->memoryMap.region[IB+i].alignment = 128;
337+
pm8001_ha->memoryMap.region[ib_offset+i].alignment
338+
= 128;
311339
} else {
312-
pm8001_ha->memoryMap.region[IB+i].num_elements =
340+
pm8001_ha->memoryMap.region[ib_offset+i].num_elements =
313341
PM8001_MPI_QUEUE;
314-
pm8001_ha->memoryMap.region[IB+i].element_size = 64;
315-
pm8001_ha->memoryMap.region[IB+i].total_len =
342+
pm8001_ha->memoryMap.region[ib_offset+i].element_size
343+
= 64;
344+
pm8001_ha->memoryMap.region[ib_offset+i].total_len =
316345
PM8001_MPI_QUEUE * 64;
317-
pm8001_ha->memoryMap.region[IB+i].alignment = 64;
346+
pm8001_ha->memoryMap.region[ib_offset+i].alignment = 64;
318347
}
319348
}
320349

321-
for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) {
350+
for (i = 0; i < count; i++) {
322351
/* MPI Memory region 4 for producer Index of outbound queues */
323-
pm8001_ha->memoryMap.region[PI+i].num_elements = 1;
324-
pm8001_ha->memoryMap.region[PI+i].element_size = 4;
325-
pm8001_ha->memoryMap.region[PI+i].total_len = 4;
326-
pm8001_ha->memoryMap.region[PI+i].alignment = 4;
352+
pm8001_ha->memoryMap.region[pi_offset+i].num_elements = 1;
353+
pm8001_ha->memoryMap.region[pi_offset+i].element_size = 4;
354+
pm8001_ha->memoryMap.region[pi_offset+i].total_len = 4;
355+
pm8001_ha->memoryMap.region[pi_offset+i].alignment = 4;
327356

328357
if (ent->driver_data != chip_8001) {
329358
/* MPI Memory region 6 Outbound queues */
330-
pm8001_ha->memoryMap.region[OB+i].num_elements =
359+
pm8001_ha->memoryMap.region[ob_offset+i].num_elements =
331360
PM8001_MPI_QUEUE;
332-
pm8001_ha->memoryMap.region[OB+i].element_size = 128;
333-
pm8001_ha->memoryMap.region[OB+i].total_len =
361+
pm8001_ha->memoryMap.region[ob_offset+i].element_size
362+
= 128;
363+
pm8001_ha->memoryMap.region[ob_offset+i].total_len =
334364
PM8001_MPI_QUEUE * 128;
335-
pm8001_ha->memoryMap.region[OB+i].alignment = 128;
365+
pm8001_ha->memoryMap.region[ob_offset+i].alignment
366+
= 128;
336367
} else {
337368
/* MPI Memory region 6 Outbound queues */
338-
pm8001_ha->memoryMap.region[OB+i].num_elements =
369+
pm8001_ha->memoryMap.region[ob_offset+i].num_elements =
339370
PM8001_MPI_QUEUE;
340-
pm8001_ha->memoryMap.region[OB+i].element_size = 64;
341-
pm8001_ha->memoryMap.region[OB+i].total_len =
371+
pm8001_ha->memoryMap.region[ob_offset+i].element_size
372+
= 64;
373+
pm8001_ha->memoryMap.region[ob_offset+i].total_len =
342374
PM8001_MPI_QUEUE * 64;
343-
pm8001_ha->memoryMap.region[OB+i].alignment = 64;
375+
pm8001_ha->memoryMap.region[ob_offset+i].alignment = 64;
344376
}
345377

346378
}
@@ -369,7 +401,7 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha,
369401
pm8001_ha->memoryMap.region[FORENSIC_MEM].total_len = 0x10000;
370402
pm8001_ha->memoryMap.region[FORENSIC_MEM].element_size = 0x10000;
371403
pm8001_ha->memoryMap.region[FORENSIC_MEM].alignment = 0x10000;
372-
for (i = 0; i < USI_MAX_MEMCNT; i++) {
404+
for (i = 0; i < pm8001_ha->max_memcnt; i++) {
373405
if (pm8001_mem_alloc(pm8001_ha->pdev,
374406
&pm8001_ha->memoryMap.region[i].virt_ptr,
375407
&pm8001_ha->memoryMap.region[i].phys_addr,
@@ -405,6 +437,8 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha,
405437
/* Initialize tags */
406438
pm8001_tag_init(pm8001_ha);
407439
return 0;
440+
err_out_shost:
441+
scsi_remove_host(pm8001_ha->shost);
408442
err_out:
409443
return 1;
410444
}
@@ -899,7 +933,8 @@ static int pm8001_configure_phy_settings(struct pm8001_hba_info *pm8001_ha)
899933
static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
900934
{
901935
u32 number_of_intr;
902-
int rc;
936+
int rc, cpu_online_count;
937+
unsigned int allocated_irq_vectors;
903938

904939
/* SPCv controllers supports 64 msi-x */
905940
if (pm8001_ha->chip_id == chip_8001) {
@@ -908,13 +943,21 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
908943
number_of_intr = PM8001_MAX_MSIX_VEC;
909944
}
910945

946+
cpu_online_count = num_online_cpus();
947+
number_of_intr = min_t(int, cpu_online_count, number_of_intr);
911948
rc = pci_alloc_irq_vectors(pm8001_ha->pdev, number_of_intr,
912949
number_of_intr, PCI_IRQ_MSIX);
913-
number_of_intr = rc;
950+
allocated_irq_vectors = rc;
914951
if (rc < 0)
915952
return rc;
953+
954+
/* Assigns the number of interrupts */
955+
number_of_intr = min_t(int, allocated_irq_vectors, number_of_intr);
916956
pm8001_ha->number_of_intr = number_of_intr;
917957

958+
/* Maximum queue number updating in HBA structure */
959+
pm8001_ha->max_q_num = number_of_intr;
960+
918961
PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
919962
"pci_alloc_irq_vectors request ret:%d no of intr %d\n",
920963
rc, pm8001_ha->number_of_intr));
@@ -1069,13 +1112,6 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
10691112
rc = -ENOMEM;
10701113
goto err_out_free;
10711114
}
1072-
/* Setup Interrupt */
1073-
rc = pm8001_setup_irq(pm8001_ha);
1074-
if (rc) {
1075-
PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
1076-
"pm8001_setup_irq failed [ret: %d]\n", rc));
1077-
goto err_out_shost;
1078-
}
10791115

10801116
PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
10811117
rc = PM8001_CHIP_DISP->chip_init(pm8001_ha);
@@ -1088,13 +1124,6 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
10881124
rc = scsi_add_host(shost, &pdev->dev);
10891125
if (rc)
10901126
goto err_out_ha_free;
1091-
/* Request Interrupt */
1092-
rc = pm8001_request_irq(pm8001_ha);
1093-
if (rc) {
1094-
PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
1095-
"pm8001_request_irq failed [ret: %d]\n", rc));
1096-
goto err_out_shost;
1097-
}
10981127

10991128
PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0);
11001129
if (pm8001_ha->chip_id != chip_8001) {

drivers/scsi/pm8001/pm8001_sas.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,7 @@ struct inbound_queue_table {
468468
u32 reserved;
469469
__le32 consumer_index;
470470
u32 producer_idx;
471+
spinlock_t iq_lock;
471472
};
472473
struct outbound_queue_table {
473474
u32 element_size_cnt;
@@ -524,8 +525,8 @@ struct pm8001_hba_info {
524525
void __iomem *fatal_tbl_addr; /*MPI IVT Table Addr */
525526
union main_cfg_table main_cfg_tbl;
526527
union general_status_table gs_tbl;
527-
struct inbound_queue_table inbnd_q_tbl[PM8001_MAX_SPCV_INB_NUM];
528-
struct outbound_queue_table outbnd_q_tbl[PM8001_MAX_SPCV_OUTB_NUM];
528+
struct inbound_queue_table inbnd_q_tbl[PM8001_MAX_INB_NUM];
529+
struct outbound_queue_table outbnd_q_tbl[PM8001_MAX_OUTB_NUM];
529530
struct sas_phy_attribute_table phy_attr_table;
530531
/* MPI SAS PHY attributes */
531532
u8 sas_addr[SAS_ADDR_SIZE];
@@ -561,6 +562,12 @@ struct pm8001_hba_info {
561562
u32 reset_in_progress;
562563
u32 non_fatal_count;
563564
u32 non_fatal_read_length;
565+
u32 max_q_num;
566+
u32 ib_offset;
567+
u32 ob_offset;
568+
u32 ci_offset;
569+
u32 pi_offset;
570+
u32 max_memcnt;
564571
};
565572

566573
struct pm8001_work {

0 commit comments

Comments
 (0)