Skip to content

Commit

Permalink
scsi: qla2xxx: Change in PUREX to handle FPIN ELS requests
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Shyam Sundar authored and Martin K. Petersen committed Jul 2, 2020
1 parent e7019c9 commit 62e9dd1
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 43 deletions.
15 changes: 13 additions & 2 deletions drivers/scsi/qla2xxx/qla_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
#include <scsi/scsi_transport_fc.h>
#include <scsi/scsi_bsg_fc.h>

#include <uapi/scsi/fc/fc_els.h>

/* Big endian Fibre Channel S_ID (source ID) or D_ID (destination ID). */
typedef struct {
uint8_t domain;
Expand Down Expand Up @@ -1304,7 +1306,6 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs)
#define RNID_TYPE_ASIC_TEMP 0xC

#define ELS_CMD_MAP_SIZE 32
#define ELS_COMMAND_RDP 0x18

/*
* Firmware state codes from get firmware state mailbox command
Expand Down Expand Up @@ -4522,10 +4523,19 @@ struct active_regions {
#define QLA_SET_DATA_RATE_NOLR 1
#define QLA_SET_DATA_RATE_LR 2 /* Set speed and initiate LR */

#define QLA_DEFAULT_PAYLOAD_SIZE 64
/*
* This item might be allocated with a size > sizeof(struct purex_item).
* The "size" variable gives the size of the payload (which
* is variable) starting at "iocb".
*/
struct purex_item {
struct list_head list;
struct scsi_qla_host *vha;
void (*process_item)(struct scsi_qla_host *vha, void *pkt);
void (*process_item)(struct scsi_qla_host *vha,
struct purex_item *pkt);
atomic_t in_use;
uint16_t size;
struct {
uint8_t iocb[64];
} iocb;
Expand Down Expand Up @@ -4725,6 +4735,7 @@ typedef struct scsi_qla_host {
struct list_head head;
spinlock_t lock;
} purex_list;
struct purex_item default_item;

struct name_list_extended gnl;
/* Count of active session/fcport */
Expand Down
3 changes: 2 additions & 1 deletion drivers/scsi/qla2xxx/qla_gbl.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,8 @@ void qla2x00_handle_login_done_event(struct scsi_qla_host *, fc_port_t *,
int qla24xx_post_gnl_work(struct scsi_qla_host *, fc_port_t *);
int qla24xx_post_relogin_work(struct scsi_qla_host *vha);
void qla2x00_wait_for_sess_deletion(scsi_qla_host_t *);
void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt);
void qla24xx_process_purex_rdp(struct scsi_qla_host *vha,
struct purex_item *pkt);

/*
* Global Functions in qla_mid.c source file.
Expand Down
116 changes: 85 additions & 31 deletions drivers/scsi/qla2xxx/qla_isr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -3280,8 +3325,12 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
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) ||
Expand Down Expand Up @@ -3332,13 +3381,18 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
{
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:
Expand Down
22 changes: 17 additions & 5 deletions drivers/scsi/qla2xxx/qla_mbx.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ static struct rom_cmd {
{ MBC_IOCB_COMMAND_A64 },
{ MBC_GET_ADAPTER_LOOP_ID },
{ MBC_READ_SFP },
{ MBC_SET_RNID_PARAMS },
{ MBC_GET_RNID_PARAMS },
{ MBC_GET_SET_ZIO_THRESHOLD },
};
Expand Down Expand Up @@ -4866,6 +4867,7 @@ qla24xx_get_port_login_templ(scsi_qla_host_t *vha, dma_addr_t buf_dma,
return rval;
}

#define PUREX_CMD_COUNT 2
int
qla25xx_set_els_cmds_supported(scsi_qla_host_t *vha)
{
Expand All @@ -4874,12 +4876,12 @@ qla25xx_set_els_cmds_supported(scsi_qla_host_t *vha)
mbx_cmd_t *mcp = &mc;
uint8_t *els_cmd_map;
dma_addr_t els_cmd_map_dma;
uint cmd_opcode = ELS_COMMAND_RDP;
uint index = cmd_opcode / 8;
uint bit = cmd_opcode % 8;
uint8_t cmd_opcode[PUREX_CMD_COUNT];
uint8_t i, index, purex_bit;
struct qla_hw_data *ha = vha->hw;

if (!IS_QLA25XX(ha) && !IS_QLA2031(ha) && !IS_QLA27XX(ha))
if (!IS_QLA25XX(ha) && !IS_QLA2031(ha) &&
!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
return QLA_SUCCESS;

ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1197,
Expand All @@ -4893,7 +4895,17 @@ qla25xx_set_els_cmds_supported(scsi_qla_host_t *vha)
return QLA_MEMORY_ALLOC_FAILED;
}

els_cmd_map[index] |= 1 << bit;
memset(els_cmd_map, 0, ELS_CMD_MAP_SIZE);

/* List of Purex ELS */
cmd_opcode[0] = ELS_FPIN;
cmd_opcode[1] = ELS_RDP;

for (i = 0; i < PUREX_CMD_COUNT; i++) {
index = cmd_opcode[i] / 8;
purex_bit = cmd_opcode[i] % 8;
els_cmd_map[index] |= 1 << purex_bit;
}

mcp->mb[0] = MBC_SET_RNID_PARAMS;
mcp->mb[1] = RNID_TYPE_ELS_CMD << 8;
Expand Down
19 changes: 15 additions & 4 deletions drivers/scsi/qla2xxx/qla_os.c
Original file line number Diff line number Diff line change
Expand Up @@ -5893,10 +5893,12 @@ qla25xx_rdp_port_speed_currently(struct qla_hw_data *ha)
* vha: SCSI qla host
* purex: RDP request received by HBA
*/
void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt)
void qla24xx_process_purex_rdp(struct scsi_qla_host *vha,
struct purex_item *item)
{
struct qla_hw_data *ha = vha->hw;
struct purex_entry_24xx *purex = pkt;
struct purex_entry_24xx *purex =
(struct purex_entry_24xx *)&item->iocb;
dma_addr_t rsp_els_dma;
dma_addr_t rsp_payload_dma;
dma_addr_t stat_dma;
Expand Down Expand Up @@ -6306,6 +6308,15 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt)
rsp_els, rsp_els_dma);
}

void
qla24xx_free_purex_item(struct purex_item *item)
{
if (item == &item->vha->default_item)
memset(&item->vha->default_item, 0, sizeof(struct purex_item));
else
kfree(item);
}

void qla24xx_process_purex_list(struct purex_list *list)
{
struct list_head head = LIST_HEAD_INIT(head);
Expand All @@ -6318,8 +6329,8 @@ void qla24xx_process_purex_list(struct purex_list *list)

list_for_each_entry_safe(item, next, &head, list) {
list_del(&item->list);
item->process_item(item->vha, &item->iocb);
kfree(item);
item->process_item(item->vha, item);
qla24xx_free_purex_item(item);
}
}

Expand Down
2 changes: 2 additions & 0 deletions include/uapi/scsi/fc/fc_els.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ enum fc_els_cmd {
ELS_REC = 0x13, /* read exchange concise */
ELS_SRR = 0x14, /* sequence retransmission request */
ELS_FPIN = 0x16, /* Fabric Performance Impact Notification */
ELS_RDP = 0x18, /* Read Diagnostic Parameters */
ELS_RDF = 0x19, /* Register Diagnostic Functions */
ELS_PRLI = 0x20, /* process login */
ELS_PRLO = 0x21, /* process logout */
Expand Down Expand Up @@ -110,6 +111,7 @@ enum fc_els_cmd {
[ELS_REC] = "REC", \
[ELS_SRR] = "SRR", \
[ELS_FPIN] = "FPIN", \
[ELS_RDP] = "RDP", \
[ELS_RDF] = "RDF", \
[ELS_PRLI] = "PRLI", \
[ELS_PRLO] = "PRLO", \
Expand Down

0 comments on commit 62e9dd1

Please sign in to comment.