Skip to content

Commit e1a4e0d

Browse files
tyreldmartinkpetersen
authored andcommitted
scsi: ibmvfc: Implement channel queue depth and event buffer accounting
Extend ibmvfc_queue, ibmvfc_event, and ibmvfc_event_pool to provide queue depths for general I/O commands and reserved commands as well as proper accounting of the free events of each type from the general event pool. Further, calculate the negotiated max command limit with the VIOS at NPIV login time as a function of the number of queues times their total queue depth (general and reserved depths combined). This does away with the legacy max_request value, and allows the driver to better manage and track it resources. Signed-off-by: Tyrel Datwyler <tyreld@linux.ibm.com> Link: https://lore.kernel.org/r/20230921225435.3537728-3-tyreld@linux.ibm.com Reviewed-by: Brian King <brking@linux.vnet.ibm.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent b39f2d1 commit e1a4e0d

2 files changed

Lines changed: 80 additions & 41 deletions

File tree

drivers/scsi/ibmvscsi/ibmvfc.c

Lines changed: 71 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ static unsigned int default_timeout = IBMVFC_DEFAULT_TIMEOUT;
3838
static u64 max_lun = IBMVFC_MAX_LUN;
3939
static unsigned int max_targets = IBMVFC_MAX_TARGETS;
4040
static unsigned int max_requests = IBMVFC_MAX_REQUESTS_DEFAULT;
41+
static u16 scsi_qdepth = IBMVFC_SCSI_QDEPTH;
4142
static unsigned int disc_threads = IBMVFC_MAX_DISC_THREADS;
4243
static unsigned int ibmvfc_debug = IBMVFC_DEBUG;
4344
static unsigned int log_level = IBMVFC_DEFAULT_LOG_LEVEL;
@@ -83,6 +84,9 @@ MODULE_PARM_DESC(default_timeout,
8384
module_param_named(max_requests, max_requests, uint, S_IRUGO);
8485
MODULE_PARM_DESC(max_requests, "Maximum requests for this adapter. "
8586
"[Default=" __stringify(IBMVFC_MAX_REQUESTS_DEFAULT) "]");
87+
module_param_named(scsi_qdepth, scsi_qdepth, ushort, S_IRUGO);
88+
MODULE_PARM_DESC(scsi_qdepth, "Maximum scsi command depth per adapter queue. "
89+
"[Default=" __stringify(IBMVFC_SCSI_QDEPTH) "]");
8690
module_param_named(max_lun, max_lun, ullong, S_IRUGO);
8791
MODULE_PARM_DESC(max_lun, "Maximum allowed LUN. "
8892
"[Default=" __stringify(IBMVFC_MAX_LUN) "]");
@@ -776,28 +780,26 @@ static int ibmvfc_send_crq_init_complete(struct ibmvfc_host *vhost)
776780
* ibmvfc_init_event_pool - Allocates and initializes the event pool for a host
777781
* @vhost: ibmvfc host who owns the event pool
778782
* @queue: ibmvfc queue struct
779-
* @size: pool size
780783
*
781784
* Returns zero on success.
782785
**/
783786
static int ibmvfc_init_event_pool(struct ibmvfc_host *vhost,
784-
struct ibmvfc_queue *queue,
785-
unsigned int size)
787+
struct ibmvfc_queue *queue)
786788
{
787789
int i;
788790
struct ibmvfc_event_pool *pool = &queue->evt_pool;
789791

790792
ENTER;
791-
if (!size)
793+
if (!queue->total_depth)
792794
return 0;
793795

794-
pool->size = size;
795-
pool->events = kcalloc(size, sizeof(*pool->events), GFP_KERNEL);
796+
pool->size = queue->total_depth;
797+
pool->events = kcalloc(pool->size, sizeof(*pool->events), GFP_KERNEL);
796798
if (!pool->events)
797799
return -ENOMEM;
798800

799801
pool->iu_storage = dma_alloc_coherent(vhost->dev,
800-
size * sizeof(*pool->iu_storage),
802+
pool->size * sizeof(*pool->iu_storage),
801803
&pool->iu_token, 0);
802804

803805
if (!pool->iu_storage) {
@@ -807,9 +809,11 @@ static int ibmvfc_init_event_pool(struct ibmvfc_host *vhost,
807809

808810
INIT_LIST_HEAD(&queue->sent);
809811
INIT_LIST_HEAD(&queue->free);
812+
queue->evt_free = queue->evt_depth;
813+
queue->reserved_free = queue->reserved_depth;
810814
spin_lock_init(&queue->l_lock);
811815

812-
for (i = 0; i < size; ++i) {
816+
for (i = 0; i < pool->size; ++i) {
813817
struct ibmvfc_event *evt = &pool->events[i];
814818

815819
/*
@@ -1033,6 +1037,12 @@ static void ibmvfc_free_event(struct ibmvfc_event *evt)
10331037

10341038
spin_lock_irqsave(&evt->queue->l_lock, flags);
10351039
list_add_tail(&evt->queue_list, &evt->queue->free);
1040+
if (evt->reserved) {
1041+
evt->reserved = 0;
1042+
evt->queue->reserved_free++;
1043+
} else {
1044+
evt->queue->evt_free++;
1045+
}
10361046
if (evt->eh_comp)
10371047
complete(evt->eh_comp);
10381048
spin_unlock_irqrestore(&evt->queue->l_lock, flags);
@@ -1475,6 +1485,12 @@ static void ibmvfc_set_login_info(struct ibmvfc_host *vhost)
14751485
struct ibmvfc_queue *async_crq = &vhost->async_crq;
14761486
struct device_node *of_node = vhost->dev->of_node;
14771487
const char *location;
1488+
u16 max_cmds;
1489+
1490+
max_cmds = scsi_qdepth + IBMVFC_NUM_INTERNAL_REQ;
1491+
if (mq_enabled)
1492+
max_cmds += (scsi_qdepth + IBMVFC_NUM_INTERNAL_SUBQ_REQ) *
1493+
vhost->client_scsi_channels;
14781494

14791495
memset(login_info, 0, sizeof(*login_info));
14801496

@@ -1489,7 +1505,7 @@ static void ibmvfc_set_login_info(struct ibmvfc_host *vhost)
14891505
if (vhost->client_migrated)
14901506
login_info->flags |= cpu_to_be16(IBMVFC_CLIENT_MIGRATED);
14911507

1492-
login_info->max_cmds = cpu_to_be32(max_requests + IBMVFC_NUM_INTERNAL_REQ);
1508+
login_info->max_cmds = cpu_to_be32(max_cmds);
14931509
login_info->capabilities = cpu_to_be64(IBMVFC_CAN_MIGRATE | IBMVFC_CAN_SEND_VF_WWPN);
14941510

14951511
if (vhost->mq_enabled || vhost->using_channels)
@@ -1508,29 +1524,39 @@ static void ibmvfc_set_login_info(struct ibmvfc_host *vhost)
15081524
}
15091525

15101526
/**
1511-
* ibmvfc_get_event - Gets the next free event in pool
1527+
* __ibmvfc_get_event - Gets the next free event in pool
15121528
* @queue: ibmvfc queue struct
1529+
* @reserved: event is for a reserved management command
15131530
*
15141531
* Returns a free event from the pool.
15151532
**/
1516-
static struct ibmvfc_event *ibmvfc_get_event(struct ibmvfc_queue *queue)
1533+
static struct ibmvfc_event *__ibmvfc_get_event(struct ibmvfc_queue *queue, int reserved)
15171534
{
1518-
struct ibmvfc_event *evt;
1535+
struct ibmvfc_event *evt = NULL;
15191536
unsigned long flags;
15201537

15211538
spin_lock_irqsave(&queue->l_lock, flags);
1522-
if (list_empty(&queue->free)) {
1523-
ibmvfc_log(queue->vhost, 4, "empty event pool on queue:%ld\n", queue->hwq_id);
1524-
spin_unlock_irqrestore(&queue->l_lock, flags);
1525-
return NULL;
1539+
if (reserved && queue->reserved_free) {
1540+
evt = list_entry(queue->free.next, struct ibmvfc_event, queue_list);
1541+
evt->reserved = 1;
1542+
queue->reserved_free--;
1543+
} else if (queue->evt_free) {
1544+
evt = list_entry(queue->free.next, struct ibmvfc_event, queue_list);
1545+
queue->evt_free--;
1546+
} else {
1547+
goto out;
15261548
}
1527-
evt = list_entry(queue->free.next, struct ibmvfc_event, queue_list);
1549+
15281550
atomic_set(&evt->free, 0);
15291551
list_del(&evt->queue_list);
1552+
out:
15301553
spin_unlock_irqrestore(&queue->l_lock, flags);
15311554
return evt;
15321555
}
15331556

1557+
#define ibmvfc_get_event(queue) __ibmvfc_get_event(queue, 0)
1558+
#define ibmvfc_get_reserved_event(queue) __ibmvfc_get_event(queue, 1)
1559+
15341560
/**
15351561
* ibmvfc_locked_done - Calls evt completion with host_lock held
15361562
* @evt: ibmvfc evt to complete
@@ -2047,7 +2073,7 @@ static int ibmvfc_bsg_timeout(struct bsg_job *job)
20472073
}
20482074

20492075
vhost->aborting_passthru = 1;
2050-
evt = ibmvfc_get_event(&vhost->crq);
2076+
evt = ibmvfc_get_reserved_event(&vhost->crq);
20512077
if (!evt) {
20522078
spin_unlock_irqrestore(vhost->host->host_lock, flags);
20532079
return -ENOMEM;
@@ -2110,7 +2136,7 @@ static int ibmvfc_bsg_plogi(struct ibmvfc_host *vhost, unsigned int port_id)
21102136
if (unlikely((rc = ibmvfc_host_chkready(vhost))))
21112137
goto unlock_out;
21122138

2113-
evt = ibmvfc_get_event(&vhost->crq);
2139+
evt = ibmvfc_get_reserved_event(&vhost->crq);
21142140
if (!evt) {
21152141
rc = -ENOMEM;
21162142
goto unlock_out;
@@ -2232,7 +2258,7 @@ static int ibmvfc_bsg_request(struct bsg_job *job)
22322258
goto out;
22332259
}
22342260

2235-
evt = ibmvfc_get_event(&vhost->crq);
2261+
evt = ibmvfc_get_reserved_event(&vhost->crq);
22362262
if (!evt) {
22372263
spin_unlock_irqrestore(vhost->host->host_lock, flags);
22382264
rc = -ENOMEM;
@@ -2533,7 +2559,7 @@ static struct ibmvfc_event *ibmvfc_init_tmf(struct ibmvfc_queue *queue,
25332559
struct ibmvfc_event *evt;
25342560
struct ibmvfc_tmf *tmf;
25352561

2536-
evt = ibmvfc_get_event(queue);
2562+
evt = ibmvfc_get_reserved_event(queue);
25372563
if (!evt)
25382564
return NULL;
25392565
ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_MAD_FORMAT);
@@ -3673,7 +3699,6 @@ static const struct scsi_host_template driver_template = {
36733699
.max_sectors = IBMVFC_MAX_SECTORS,
36743700
.shost_groups = ibmvfc_host_groups,
36753701
.track_queue_depth = 1,
3676-
.host_tagset = 1,
36773702
};
36783703

36793704
/**
@@ -4071,7 +4096,7 @@ static void ibmvfc_tgt_send_prli(struct ibmvfc_target *tgt)
40714096
return;
40724097

40734098
kref_get(&tgt->kref);
4074-
evt = ibmvfc_get_event(&vhost->crq);
4099+
evt = ibmvfc_get_reserved_event(&vhost->crq);
40754100
if (!evt) {
40764101
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
40774102
kref_put(&tgt->kref, ibmvfc_release_tgt);
@@ -4184,7 +4209,7 @@ static void ibmvfc_tgt_send_plogi(struct ibmvfc_target *tgt)
41844209

41854210
kref_get(&tgt->kref);
41864211
tgt->logo_rcvd = 0;
4187-
evt = ibmvfc_get_event(&vhost->crq);
4212+
evt = ibmvfc_get_reserved_event(&vhost->crq);
41884213
if (!evt) {
41894214
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
41904215
kref_put(&tgt->kref, ibmvfc_release_tgt);
@@ -4266,7 +4291,7 @@ static struct ibmvfc_event *__ibmvfc_tgt_get_implicit_logout_evt(struct ibmvfc_t
42664291
struct ibmvfc_event *evt;
42674292

42684293
kref_get(&tgt->kref);
4269-
evt = ibmvfc_get_event(&vhost->crq);
4294+
evt = ibmvfc_get_reserved_event(&vhost->crq);
42704295
if (!evt)
42714296
return NULL;
42724297
ibmvfc_init_event(evt, done, IBMVFC_MAD_FORMAT);
@@ -4441,7 +4466,7 @@ static void ibmvfc_tgt_move_login(struct ibmvfc_target *tgt)
44414466
return;
44424467

44434468
kref_get(&tgt->kref);
4444-
evt = ibmvfc_get_event(&vhost->crq);
4469+
evt = ibmvfc_get_reserved_event(&vhost->crq);
44454470
if (!evt) {
44464471
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
44474472
kref_put(&tgt->kref, ibmvfc_release_tgt);
@@ -4613,7 +4638,7 @@ static void ibmvfc_adisc_timeout(struct timer_list *t)
46134638

46144639
vhost->abort_threads++;
46154640
kref_get(&tgt->kref);
4616-
evt = ibmvfc_get_event(&vhost->crq);
4641+
evt = ibmvfc_get_reserved_event(&vhost->crq);
46174642
if (!evt) {
46184643
tgt_err(tgt, "Failed to get cancel event for ADISC.\n");
46194644
vhost->abort_threads--;
@@ -4671,7 +4696,7 @@ static void ibmvfc_tgt_adisc(struct ibmvfc_target *tgt)
46714696
return;
46724697

46734698
kref_get(&tgt->kref);
4674-
evt = ibmvfc_get_event(&vhost->crq);
4699+
evt = ibmvfc_get_reserved_event(&vhost->crq);
46754700
if (!evt) {
46764701
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
46774702
kref_put(&tgt->kref, ibmvfc_release_tgt);
@@ -4780,7 +4805,7 @@ static void ibmvfc_tgt_query_target(struct ibmvfc_target *tgt)
47804805
return;
47814806

47824807
kref_get(&tgt->kref);
4783-
evt = ibmvfc_get_event(&vhost->crq);
4808+
evt = ibmvfc_get_reserved_event(&vhost->crq);
47844809
if (!evt) {
47854810
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
47864811
kref_put(&tgt->kref, ibmvfc_release_tgt);
@@ -4958,7 +4983,7 @@ static void ibmvfc_discover_targets_done(struct ibmvfc_event *evt)
49584983
static void ibmvfc_discover_targets(struct ibmvfc_host *vhost)
49594984
{
49604985
struct ibmvfc_discover_targets *mad;
4961-
struct ibmvfc_event *evt = ibmvfc_get_event(&vhost->crq);
4986+
struct ibmvfc_event *evt = ibmvfc_get_reserved_event(&vhost->crq);
49624987
int level = IBMVFC_DEFAULT_LOG_LEVEL;
49634988

49644989
if (!evt) {
@@ -5039,7 +5064,7 @@ static void ibmvfc_channel_setup(struct ibmvfc_host *vhost)
50395064
{
50405065
struct ibmvfc_channel_setup_mad *mad;
50415066
struct ibmvfc_channel_setup *setup_buf = vhost->channel_setup_buf;
5042-
struct ibmvfc_event *evt = ibmvfc_get_event(&vhost->crq);
5067+
struct ibmvfc_event *evt = ibmvfc_get_reserved_event(&vhost->crq);
50435068
struct ibmvfc_scsi_channels *scrqs = &vhost->scsi_scrqs;
50445069
unsigned int num_channels =
50455070
min(vhost->client_scsi_channels, vhost->max_vios_scsi_channels);
@@ -5112,7 +5137,7 @@ static void ibmvfc_channel_enquiry_done(struct ibmvfc_event *evt)
51125137
static void ibmvfc_channel_enquiry(struct ibmvfc_host *vhost)
51135138
{
51145139
struct ibmvfc_channel_enquiry *mad;
5115-
struct ibmvfc_event *evt = ibmvfc_get_event(&vhost->crq);
5140+
struct ibmvfc_event *evt = ibmvfc_get_reserved_event(&vhost->crq);
51165141
int level = IBMVFC_DEFAULT_LOG_LEVEL;
51175142

51185143
if (!evt) {
@@ -5240,7 +5265,7 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt)
52405265
static void ibmvfc_npiv_login(struct ibmvfc_host *vhost)
52415266
{
52425267
struct ibmvfc_npiv_login_mad *mad;
5243-
struct ibmvfc_event *evt = ibmvfc_get_event(&vhost->crq);
5268+
struct ibmvfc_event *evt = ibmvfc_get_reserved_event(&vhost->crq);
52445269

52455270
if (!evt) {
52465271
ibmvfc_dbg(vhost, "NPIV Login failed: no available events\n");
@@ -5311,7 +5336,7 @@ static void ibmvfc_npiv_logout(struct ibmvfc_host *vhost)
53115336
struct ibmvfc_npiv_logout_mad *mad;
53125337
struct ibmvfc_event *evt;
53135338

5314-
evt = ibmvfc_get_event(&vhost->crq);
5339+
evt = ibmvfc_get_reserved_event(&vhost->crq);
53155340
if (!evt) {
53165341
ibmvfc_dbg(vhost, "NPIV Logout failed: no available events\n");
53175342
ibmvfc_hard_reset_host(vhost);
@@ -5765,7 +5790,6 @@ static int ibmvfc_alloc_queue(struct ibmvfc_host *vhost,
57655790
{
57665791
struct device *dev = vhost->dev;
57675792
size_t fmt_size;
5768-
unsigned int pool_size = 0;
57695793

57705794
ENTER;
57715795
spin_lock_init(&queue->_lock);
@@ -5774,22 +5798,27 @@ static int ibmvfc_alloc_queue(struct ibmvfc_host *vhost,
57745798
switch (fmt) {
57755799
case IBMVFC_CRQ_FMT:
57765800
fmt_size = sizeof(*queue->msgs.crq);
5777-
pool_size = max_requests + IBMVFC_NUM_INTERNAL_REQ;
5801+
queue->total_depth = scsi_qdepth + IBMVFC_NUM_INTERNAL_REQ;
5802+
queue->evt_depth = scsi_qdepth;
5803+
queue->reserved_depth = IBMVFC_NUM_INTERNAL_REQ;
57785804
break;
57795805
case IBMVFC_ASYNC_FMT:
57805806
fmt_size = sizeof(*queue->msgs.async);
57815807
break;
57825808
case IBMVFC_SUB_CRQ_FMT:
57835809
fmt_size = sizeof(*queue->msgs.scrq);
57845810
/* We need one extra event for Cancel Commands */
5785-
pool_size = max_requests + 1;
5811+
queue->total_depth = scsi_qdepth + IBMVFC_NUM_INTERNAL_SUBQ_REQ;
5812+
queue->evt_depth = scsi_qdepth;
5813+
queue->reserved_depth = IBMVFC_NUM_INTERNAL_SUBQ_REQ;
57865814
break;
57875815
default:
57885816
dev_warn(dev, "Unknown command/response queue message format: %d\n", fmt);
57895817
return -EINVAL;
57905818
}
57915819

5792-
if (ibmvfc_init_event_pool(vhost, queue, pool_size)) {
5820+
queue->fmt = fmt;
5821+
if (ibmvfc_init_event_pool(vhost, queue)) {
57935822
dev_err(dev, "Couldn't initialize event pool.\n");
57945823
return -ENOMEM;
57955824
}
@@ -5808,7 +5837,6 @@ static int ibmvfc_alloc_queue(struct ibmvfc_host *vhost,
58085837
}
58095838

58105839
queue->cur = 0;
5811-
queue->fmt = fmt;
58125840
queue->size = PAGE_SIZE / fmt_size;
58135841

58145842
queue->vhost = vhost;
@@ -6243,7 +6271,7 @@ static int ibmvfc_probe(struct vio_dev *vdev, const struct vio_device_id *id)
62436271
}
62446272

62456273
shost->transportt = ibmvfc_transport_template;
6246-
shost->can_queue = max_requests;
6274+
shost->can_queue = scsi_qdepth;
62476275
shost->max_lun = max_lun;
62486276
shost->max_id = max_targets;
62496277
shost->max_sectors = IBMVFC_MAX_SECTORS;
@@ -6402,7 +6430,9 @@ static int ibmvfc_resume(struct device *dev)
64026430
*/
64036431
static unsigned long ibmvfc_get_desired_dma(struct vio_dev *vdev)
64046432
{
6405-
unsigned long pool_dma = max_requests * sizeof(union ibmvfc_iu);
6433+
unsigned long pool_dma;
6434+
6435+
pool_dma = (IBMVFC_MAX_SCSI_QUEUES * scsi_qdepth) * sizeof(union ibmvfc_iu);
64066436
return pool_dma + ((512 * 1024) * driver_template.cmd_per_lun);
64076437
}
64086438

0 commit comments

Comments
 (0)