diff options
author | Shyam Sundar <ssundar@marvell.com> | 2020-06-30 03:22:28 -0700 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2020-07-01 22:24:16 -0400 |
commit | 62e9dd177732843ae6c5b9d2ed61e7c9538fa276 (patch) | |
tree | e0b1794b96986a3408aca57647fef1b63ebd9777 /drivers/scsi/qla2xxx/qla_isr.c | |
parent | e7019c95c40daf8e8a9fa1d5f36eabce2eb8ef6b (diff) | |
download | lwn-62e9dd177732843ae6c5b9d2ed61e7c9538fa276.tar.gz lwn-62e9dd177732843ae6c5b9d2ed61e7c9538fa276.zip |
scsi: qla2xxx: Change in PUREX to handle FPIN ELS requests
SAN Congestion Management generates ELS pkts whose size can vary and be >
64 bytes. Change the PUREX handling code to support non-standard ELS pkt
size.
Link: https://lore.kernel.org/r/20200630102229.29660-2-njavali@marvell.com
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: Shyam Sundar <ssundar@marvell.com>
Signed-off-by: Arun Easi <aeasi@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_isr.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 116 |
1 files changed, 85 insertions, 31 deletions
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index cf0800546740..3bbfff20e3a6 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -31,35 +31,11 @@ const char *const port_state_str[] = { "ONLINE" }; -static void qla24xx_purex_iocb(scsi_qla_host_t *vha, void *pkt, - void (*process_item)(struct scsi_qla_host *vha, void *pkt)) -{ - struct purex_list *list = &vha->purex_list; - struct purex_item *item; - ulong flags; - - item = kzalloc(sizeof(*item), GFP_KERNEL); - if (!item) { - ql_log(ql_log_warn, vha, 0x5092, - ">> Failed allocate purex list item.\n"); - return; - } - - item->vha = vha; - item->process_item = process_item; - memcpy(&item->iocb, pkt, sizeof(item->iocb)); - - spin_lock_irqsave(&list->lock, flags); - list_add_tail(&item->list, &list->head); - spin_unlock_irqrestore(&list->lock, flags); - - set_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags); -} - static void -qla24xx_process_abts(struct scsi_qla_host *vha, void *pkt) +qla24xx_process_abts(struct scsi_qla_host *vha, struct purex_item *pkt) { - struct abts_entry_24xx *abts = pkt; + struct abts_entry_24xx *abts = + (struct abts_entry_24xx *)&pkt->iocb; struct qla_hw_data *ha = vha->hw; struct els_entry_24xx *rsp_els; struct abts_entry_24xx *abts_rsp; @@ -789,6 +765,74 @@ qla27xx_handle_8200_aen(scsi_qla_host_t *vha, uint16_t *mb) } } +struct purex_item * +qla24xx_alloc_purex_item(scsi_qla_host_t *vha, uint16_t size) +{ + struct purex_item *item = NULL; + uint8_t item_hdr_size = sizeof(*item); + + if (size > QLA_DEFAULT_PAYLOAD_SIZE) { + item = kzalloc(item_hdr_size + + (size - QLA_DEFAULT_PAYLOAD_SIZE), GFP_ATOMIC); + } else { + if (atomic_inc_return(&vha->default_item.in_use) == 1) { + item = &vha->default_item; + goto initialize_purex_header; + } else { + item = kzalloc(item_hdr_size, GFP_ATOMIC); + } + } + if (!item) { + ql_log(ql_log_warn, vha, 0x5092, + ">> Failed allocate purex list item.\n"); + + return NULL; + } + +initialize_purex_header: + item->vha = vha; + item->size = size; + return item; +} + +static void +qla24xx_queue_purex_item(scsi_qla_host_t *vha, struct purex_item *pkt, + void (*process_item)(struct scsi_qla_host *vha, + struct purex_item *pkt)) +{ + struct purex_list *list = &vha->purex_list; + ulong flags; + + pkt->process_item = process_item; + + spin_lock_irqsave(&list->lock, flags); + list_add_tail(&pkt->list, &list->head); + spin_unlock_irqrestore(&list->lock, flags); + + set_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags); +} + +/** + * qla24xx_copy_std_pkt() - Copy over purex ELS which is + * contained in a single IOCB. + * purex packet. + * @vha: SCSI driver HA context + * @pkt: ELS packet + */ +struct purex_item +*qla24xx_copy_std_pkt(struct scsi_qla_host *vha, void *pkt) +{ + struct purex_item *item; + + item = qla24xx_alloc_purex_item(vha, + QLA_DEFAULT_PAYLOAD_SIZE); + if (!item) + return item; + + memcpy(&item->iocb, pkt, sizeof(item->iocb)); + return item; +} + /** * qla2x00_async_event() - Process aynchronous events. * @vha: SCSI driver HA context @@ -3229,6 +3273,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, { struct sts_entry_24xx *pkt; struct qla_hw_data *ha = vha->hw; + struct purex_item *pure_item; if (!ha->flags.fw_started) return; @@ -3280,8 +3325,12 @@ process_err: break; case ABTS_RECV_24XX: if (qla_ini_mode_enabled(vha)) { - qla24xx_purex_iocb(vha, pkt, - qla24xx_process_abts); + pure_item = qla24xx_copy_std_pkt(vha, pkt); + if (!pure_item) + break; + + qla24xx_queue_purex_item(vha, pure_item, + qla24xx_process_abts); break; } if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || @@ -3332,13 +3381,18 @@ process_err: { struct purex_entry_24xx *purex = (void *)pkt; - if (purex->els_frame_payload[3] != ELS_COMMAND_RDP) { + if (purex->els_frame_payload[3] != ELS_RDP) { ql_dbg(ql_dbg_init, vha, 0x5091, "Discarding ELS Request opcode %#x...\n", purex->els_frame_payload[3]); break; } - qla24xx_purex_iocb(vha, pkt, qla24xx_process_purex_rdp); + pure_item = qla24xx_copy_std_pkt(vha, pkt); + if (!pure_item) + break; + + qla24xx_queue_purex_item(vha, pure_item, + qla24xx_process_purex_rdp); break; } default: |