> So please add defines for the individual messages and use a key-value
map to lookup the messages.
FW events are in sequence 0...5 so key is implied and value is being
stored in array of strings.
BEISCSI_PORT_MISCONF_EVENT_MAX (replaced with ARRAY_SIZE) is just to
verify the event number.
Not so sure what you are suggesting.

port_name IOCTL is needed to display the error message.

Will split FW config validation.

Thanks,

JB

-----Original Message-----
From: Hannes Reinecke [mailto:h...@suse.de]
Sent: Monday, December 14, 2015 8:49 PM
To: Jitendra Bhivare; linux-scsi@vger.kernel.org; micha...@cs.wisc.edu
Subject: Re: [PATCH 5/9] be2iscsi: Fix to handle misconfigured optics
events

On 12/14/2015 07:11 AM, Jitendra Bhivare wrote:
> From: Jitendra <jitendra.bhiv...@avagotech.com>
>
> Log messages for misconfigured transceivers reported by FW.
>
> Register async events that driver handles using MCC_CREATE_EXT ioctl.
> Errors messages for faulted/uncertified/unqualified optics are logged.
> Added FW config validation.
>
> Signed-off-by: Jitendra <jitendra.bhiv...@avagotech.com>
> ---
>   drivers/scsi/be2iscsi/be_cmds.c |  169 ++++++++++++++++++-----------
>   drivers/scsi/be2iscsi/be_cmds.h |   47 +++++++-
>   drivers/scsi/be2iscsi/be_main.c |   22 +---
>   drivers/scsi/be2iscsi/be_main.h |   12 ++-
>   drivers/scsi/be2iscsi/be_mgmt.c |  230
+++++++++++++++++++++++++++------------
>   drivers/scsi/be2iscsi/be_mgmt.h |    2 +
>   6 files changed, 327 insertions(+), 155 deletions(-)
>
> diff --git a/drivers/scsi/be2iscsi/be_cmds.c
> b/drivers/scsi/be2iscsi/be_cmds.c index e4cc98f..58a9fda 100644
> --- a/drivers/scsi/be2iscsi/be_cmds.c
> +++ b/drivers/scsi/be2iscsi/be_cmds.c
> @@ -267,26 +267,6 @@ void free_mcc_tag(struct be_ctrl_info *ctrl,
unsigned int tag)
>       spin_unlock(&ctrl->mcc_lock);
>   }
>
> -bool is_link_state_evt(u32 trailer)
> -{
> -     return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
> -               ASYNC_TRAILER_EVENT_CODE_MASK) ==
> -               ASYNC_EVENT_CODE_LINK_STATE);
> -}
> -
> -static bool is_iscsi_evt(u32 trailer) -{
> -     return ((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
> -               ASYNC_TRAILER_EVENT_CODE_MASK) ==
> -               ASYNC_EVENT_CODE_ISCSI;
> -}
> -
> -static int iscsi_evt_type(u32 trailer) -{
> -     return (trailer >> ASYNC_TRAILER_EVENT_TYPE_SHIFT) &
> -              ASYNC_TRAILER_EVENT_TYPE_MASK;
> -}
> -
>   static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl)
>   {
>       if (compl->flags != 0) {
> @@ -343,7 +323,7 @@ static int be_mcc_compl_process(struct be_ctrl_info
*ctrl,
>                       if (resp_hdr->response_length)
>                               return 0;
>               }
> -             return -EBUSY;
> +             return -EINVAL;
>       }
>       return 0;
>   }
How is this related to the above description?
Shouldn't it be moved to a different patch?

> @@ -422,7 +402,7 @@ void beiscsi_fail_session(struct iscsi_cls_session
*cls_session)
>       iscsi_session_failure(cls_session->dd_data,
ISCSI_ERR_CONN_FAILED);
>   }
>
> -void beiscsi_async_link_state_process(struct beiscsi_hba *phba,
> +static void beiscsi_async_link_state_process(struct beiscsi_hba
> +*phba,
>               struct be_async_event_link_state *evt)
>   {
>       if ((evt->port_link_status == ASYNC_EVENT_LINK_DOWN) || @@ -450,6
> +430,103 @@ void beiscsi_async_link_state_process(struct beiscsi_hba
*phba,
>       }
>   }
>
> +static char *beiscsi_port_misconf_event_msg[] = {
> +     "Physical Link is functional.",
> +     "Optics faulted/incorrectly installed/not installed - Reseat
optics, if issue not resolved, replace.",
> +     "Optics of two types installed - Remove one optic or install
matching pair of optics.",
> +     "Incompatible optics - Replace with compatible optics for card to
function.",
> +     "Unqualified optics - Replace with Avago optics for Warranty and
Technical Support.",
> +     "Uncertified optics - Replace with Avago Certified optics to
enable link operation."
> +};
> +#define BEISCSI_PORT_MISCONF_EVENT_MAX \
> +     (sizeof(beiscsi_port_misconf_event_msg) / \
> +      sizeof(beiscsi_port_misconf_event_msg[0]))
> +
Please don't. The above list is tied with event numbers from firmware, and
by no means arbitrary.
So please add defines for the individual messages and use a key-value map
to lookup the messages.

> +static void beiscsi_process_async_sli(struct beiscsi_hba *phba,
> +                                   struct be_mcc_compl *compl) {
> +     struct be_async_event_sli *async_sli;
> +     u8 evt_type, state, old_state, le;
> +     char *sev = KERN_WARNING;
> +     char *msg = NULL;
> +
> +     evt_type = compl->flags >> ASYNC_TRAILER_EVENT_TYPE_SHIFT;
> +     evt_type &= ASYNC_TRAILER_EVENT_TYPE_MASK;
> +
> +     /* processing only MISCONFIGURED physical port event */
> +     if (evt_type != ASYNC_SLI_EVENT_TYPE_MISCONFIGURED)
> +             return;
> +
> +     async_sli = (struct be_async_event_sli *)compl;
> +     state = async_sli->event_data1 >>
> +              (phba->fw_config.phys_port * 8) & 0xff;
> +     le = async_sli->event_data2 >>
> +              (phba->fw_config.phys_port * 8) & 0xff;
> +
> +     old_state = phba->optic_state;
> +     phba->optic_state = state;
> +
> +     if (state >= BEISCSI_PORT_MISCONF_EVENT_MAX) {
> +             /* fw is reporting a state we don't know, log and return
*/
> +             __beiscsi_log(phba, KERN_ERR,
> +                         "BC_%d : Port %c: Unrecognized optic state
0x%x\n",
> +                         phba->port_name, async_sli->event_data1);
> +             return;
> +     }
> +
> +     if (ASYNC_SLI_LINK_EFFECT_VALID(le)) {
> +             /* log link effect for unqualified-4, uncertified-5 optics
*/
> +             if (state > 3)
> +                     msg = (ASYNC_SLI_LINK_EFFECT_STATE(le)) ?
> +                             " Link is non-operational." :
> +                             " Link is operational.";
> +             /* 1 - info */
> +             if (ASYNC_SLI_LINK_EFFECT_SEV(le) == 1)
> +                     sev = KERN_INFO;
> +             /* 2 - error */
> +             if (ASYNC_SLI_LINK_EFFECT_SEV(le) == 2)
> +                     sev = KERN_ERR;
> +     }
> +
> +     if (old_state != phba->optic_state)
> +             __beiscsi_log(phba, sev, "BC_%d : Port %c: %s%s\n",
> +                           phba->port_name,
> +                           beiscsi_port_misconf_event_msg[state],
> +                           !msg ? "" : msg);
> +}
> +
> +void beiscsi_process_async_event(struct beiscsi_hba *phba,
> +                             struct be_mcc_compl *compl)
> +{
> +     char *sev = KERN_INFO;
> +     u8 evt_code;
> +
> +     /* interpret flags as an async trailer */
> +     evt_code = compl->flags >> ASYNC_TRAILER_EVENT_CODE_SHIFT;
> +     evt_code &= ASYNC_TRAILER_EVENT_CODE_MASK;
> +     switch (evt_code) {
> +     case ASYNC_EVENT_CODE_LINK_STATE:
> +             beiscsi_async_link_state_process(phba,
> +                             (struct be_async_event_link_state
*)compl);
> +             break;
> +     case ASYNC_EVENT_CODE_ISCSI:
> +             phba->state |= BE_ADAPTER_CHECK_BOOT;
> +             phba->get_boot = BE_GET_BOOT_RETRIES;
> +             sev = KERN_ERR;
> +             break;
> +     case ASYNC_EVENT_CODE_SLI:
> +             beiscsi_process_async_sli(phba, compl);
> +             break;
> +     default:
> +             /* event not registered */
> +             sev = KERN_ERR;
> +     }
> +
> +     beiscsi_log(phba, sev, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
> +                 "BC_%d : ASYNC Event: status 0x%08x flags 0x%08x\n",
> +                 compl->status, compl->flags);
> +}
> +
>   int beiscsi_process_mcc(struct beiscsi_hba *phba)
>   {
>       struct be_mcc_compl *compl;
> @@ -459,45 +536,10 @@ int beiscsi_process_mcc(struct beiscsi_hba *phba)
>       spin_lock_bh(&phba->ctrl.mcc_cq_lock);
>       while ((compl = be_mcc_compl_get(phba))) {
>               if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
> -                     /* Interpret flags as an async trailer */
> -                     if (is_link_state_evt(compl->flags))
> -                             /* Interpret compl as a async link evt */
> -                             beiscsi_async_link_state_process(phba,
> -                                (struct be_async_event_link_state *)
compl);
> -                     else if (is_iscsi_evt(compl->flags)) {
> -                             switch (iscsi_evt_type(compl->flags)) {
> -                             case ASYNC_EVENT_NEW_ISCSI_TGT_DISC:
> -                             case ASYNC_EVENT_NEW_ISCSI_CONN:
> -                             case ASYNC_EVENT_NEW_TCP_CONN:
> -                                     phba->state |=
BE_ADAPTER_CHECK_BOOT;
> -                                     phba->get_boot =
BE_GET_BOOT_RETRIES;
> -                                     beiscsi_log(phba, KERN_ERR,
> -                                                 BEISCSI_LOG_CONFIG |
> -                                                 BEISCSI_LOG_MBOX,
> -                                                 "BC_%d : Async iscsi
Event,"
> -                                                 " flags handled =
0x%08x\n",
> -                                                 compl->flags);
> -                                     break;
> -                             default:
> -                                     phba->state |=
BE_ADAPTER_CHECK_BOOT;
> -                                     phba->get_boot =
BE_GET_BOOT_RETRIES;
> -                                     beiscsi_log(phba, KERN_ERR,
> -                                                 BEISCSI_LOG_CONFIG |
> -                                                 BEISCSI_LOG_MBOX,
> -                                                 "BC_%d : Unsupported
Async"
> -                                                 " Event, flags =
0x%08x\n",
> -                                                 compl->flags);
> -                             }
> -                     } else
> -                             beiscsi_log(phba, KERN_ERR,
> -                                         BEISCSI_LOG_CONFIG |
> -                                         BEISCSI_LOG_MBOX,
> -                                         "BC_%d : Unsupported Async
Event, flags"
> -                                         " = 0x%08x\n", compl->flags);
> -
> +                     beiscsi_process_async_event(phba, compl);
>               } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
> -                             status = be_mcc_compl_process(ctrl,
compl);
> -                             atomic_dec(&phba->ctrl.mcc_obj.q.used);
> +                     status = be_mcc_compl_process(ctrl, compl);
> +                     atomic_dec(&phba->ctrl.mcc_obj.q.used);
>               }
>               be_mcc_compl_use(compl);
>               num++;
> @@ -1013,7 +1055,7 @@ int beiscsi_cmd_mccq_create(struct beiscsi_hba
*phba,
>                       struct be_queue_info *cq)
>   {
>       struct be_mcc_wrb *wrb;
> -     struct be_cmd_req_mcc_create *req;
> +     struct be_cmd_req_mcc_create_ext *req;
>       struct be_dma_mem *q_mem = &mccq->dma_mem;
>       struct be_ctrl_info *ctrl;
>       void *ctxt;
> @@ -1029,9 +1071,12 @@ int beiscsi_cmd_mccq_create(struct beiscsi_hba
*phba,
>       be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
>
>       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
> -                     OPCODE_COMMON_MCC_CREATE, sizeof(*req));
> +                     OPCODE_COMMON_MCC_CREATE_EXT, sizeof(*req));
>
>       req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
> +     req->async_evt_bitmap = 1 << ASYNC_EVENT_CODE_LINK_STATE;
> +     req->async_evt_bitmap |= 1 << ASYNC_EVENT_CODE_ISCSI;
> +     req->async_evt_bitmap |= 1 << ASYNC_EVENT_CODE_SLI;
>
>       AMAP_SET_BITS(struct amap_mcc_context, fid, ctxt,
>                     PCI_FUNC(phba->pcidev->devfn)); diff --git
> a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h
> index 5d165ee..6411f7b 100644
> --- a/drivers/scsi/be2iscsi/be_cmds.h
> +++ b/drivers/scsi/be2iscsi/be_cmds.h
> @@ -119,13 +119,22 @@ struct be_mcc_compl {
>   #define ASYNC_TRAILER_EVENT_CODE_MASK       0xFF
>   #define ASYNC_EVENT_CODE_LINK_STATE 0x1
>   #define ASYNC_EVENT_CODE_ISCSI              0x4
> +#define ASYNC_EVENT_CODE_SLI         0x11
>
>   #define ASYNC_TRAILER_EVENT_TYPE_SHIFT      16      /* bits 16 - 23 */
> -#define ASYNC_TRAILER_EVENT_TYPE_MASK        0xF
> +#define ASYNC_TRAILER_EVENT_TYPE_MASK        0xFF
> +
> +/* iSCSI events */
>   #define ASYNC_EVENT_NEW_ISCSI_TGT_DISC      0x4
>   #define ASYNC_EVENT_NEW_ISCSI_CONN  0x5
>   #define ASYNC_EVENT_NEW_TCP_CONN    0x7
>
> +/* SLI events */
> +#define ASYNC_SLI_EVENT_TYPE_MISCONFIGURED   0x9
> +#define ASYNC_SLI_LINK_EFFECT_VALID(le)              (le & 0x80)
> +#define ASYNC_SLI_LINK_EFFECT_SEV(le)                ((le >> 1)  &
0x03)
> +#define ASYNC_SLI_LINK_EFFECT_STATE(le)              (le & 0x01)
> +
>   struct be_async_event_trailer {
>       u32 code;
>   };
> @@ -153,6 +162,16 @@ struct be_async_event_link_state {
>       struct be_async_event_trailer trailer;
>   } __packed;
>
> +/**
> + * When async-trailer is SLI event, mcc_compl is interpreted as  */
> +struct be_async_event_sli {
> +     u32 event_data1;
> +     u32 event_data2;
> +     u32 reserved;
> +     u32 trailer;
> +} __packed;
> +
>   struct be_mcc_mailbox {
>       struct be_mcc_wrb wrb;
>       struct be_mcc_compl compl;
> @@ -172,6 +191,7 @@ struct be_mcc_mailbox {
>   #define OPCODE_COMMON_CQ_CREATE                             12
>   #define OPCODE_COMMON_EQ_CREATE                             13
>   #define OPCODE_COMMON_MCC_CREATE                    21
> +#define OPCODE_COMMON_MCC_CREATE_EXT                 90
>   #define OPCODE_COMMON_ADD_TEMPLATE_HEADER_BUFFERS   24
>   #define OPCODE_COMMON_REMOVE_TEMPLATE_HEADER_BUFFERS        25
>   #define OPCODE_COMMON_GET_CNTL_ATTRIBUTES           32
> @@ -183,6 +203,7 @@ struct be_mcc_mailbox {
>   #define OPCODE_COMMON_EQ_DESTROY                    55
>   #define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG         58
>   #define OPCODE_COMMON_FUNCTION_RESET                        61
> +#define OPCODE_COMMON_GET_PORT_NAME                  77
>
>   /**
>    * LIST of opcodes that are common between Initiator and Target @@
> -587,10 +608,11 @@ struct amap_mcc_context {
>       u8 rsvd2[32];
>   } __packed;
>
> -struct be_cmd_req_mcc_create {
> +struct be_cmd_req_mcc_create_ext {
>       struct be_cmd_req_hdr hdr;
>       u16 num_pages;
>       u16 rsvd0;
> +     u32 async_evt_bitmap;
>       u8 context[sizeof(struct amap_mcc_context) / 8];
>       struct phys_addr pages[8];
>   } __packed;
> @@ -748,8 +770,8 @@ struct be_mcc_wrb *wrb_from_mccq(struct beiscsi_hba
*phba);
>   int be_mcc_notify_wait(struct beiscsi_hba *phba);
>   void be_mcc_notify(struct beiscsi_hba *phba);
>   unsigned int alloc_mcc_tag(struct beiscsi_hba *phba); -void
> beiscsi_async_link_state_process(struct beiscsi_hba *phba,
> -             struct be_async_event_link_state *evt);
> +void beiscsi_process_async_event(struct beiscsi_hba *phba,
> +                             struct be_mcc_compl *compl);
>   int be_mcc_compl_process_isr(struct be_ctrl_info *ctrl,
>                                   struct be_mcc_compl *compl);
>
> @@ -777,8 +799,6 @@ int be_cmd_wrbq_create(struct be_ctrl_info *ctrl,
struct be_dma_mem *q_mem,
>                      struct hwi_wrb_context *pwrb_context,
>                      uint8_t ulp_num);
>
> -bool is_link_state_evt(u32 trailer);
> -
>   /* Configuration Functions */
>   int be_cmd_set_vlan(struct beiscsi_hba *phba, uint16_t vlan_tag);
>
> @@ -1137,6 +1157,21 @@ struct be_cmd_get_all_if_id_req {
>       u32 if_hndl_list[1];
>   } __packed;
>
> +struct be_cmd_get_port_name {
> +     union {
> +             struct be_cmd_req_hdr req_hdr;
> +             struct be_cmd_resp_hdr resp_hdr;
> +     } h;
> +     union {
> +             struct {
> +                     u32 reserved;
> +             } req;
> +             struct {
> +                     u32 port_names;
> +             } resp;
> +     } p;
> +} __packed;
> +
>   #define ISCSI_OPCODE_SCSI_DATA_OUT          5
>   #define OPCODE_COMMON_NTWK_LINK_STATUS_QUERY 5
>   #define OPCODE_COMMON_MODIFY_EQ_DELAY               41
What does this have to do with misconfigured optics?
Please move to a separate patch.

> diff --git a/drivers/scsi/be2iscsi/be_main.c
> b/drivers/scsi/be2iscsi/be_main.c index 2f3e118..d036706 100644
> --- a/drivers/scsi/be2iscsi/be_main.c
> +++ b/drivers/scsi/be2iscsi/be_main.c
> @@ -2048,21 +2048,7 @@ static void  beiscsi_process_mcc_isr(struct
beiscsi_hba *phba)
>                       num_processed = 0;
>               }
>               if (mcc_compl->flags & CQE_FLAGS_ASYNC_MASK) {
> -                     /* Interpret flags as an async trailer */
> -                     if (is_link_state_evt(mcc_compl->flags))
> -                             /* Interpret compl as a async link evt */
> -                             beiscsi_async_link_state_process(phba,
> -                             (struct be_async_event_link_state *)
mcc_compl);
> -                     else {
> -                             beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_MBOX,
> -                                         "BM_%d :  Unsupported Async
Event, flags"
> -                                         " = 0x%08x\n",
> -                                         mcc_compl->flags);
> -                             if (phba->state & BE_ADAPTER_LINK_UP) {
> -                                     phba->state |=
BE_ADAPTER_CHECK_BOOT;
> -                                     phba->get_boot =
BE_GET_BOOT_RETRIES;
> -                             }
> -                     }
> +                     beiscsi_process_async_event(phba, mcc_compl);
>               } else if (mcc_compl->flags & CQE_FLAGS_COMPLETED_MASK) {
>                       be_mcc_compl_process_isr(&phba->ctrl, mcc_compl);
>                       atomic_dec(&phba->ctrl.mcc_obj.q.used);
> @@ -3868,6 +3854,8 @@ static int hwi_init_port(struct beiscsi_hba *phba)
>       phwi_context->min_eqd = 0;
>       phwi_context->cur_eqd = 0;
>       be_cmd_fw_initialize(&phba->ctrl);
> +     /* set optic state to unknown */
> +     phba->optic_state = 0xff;
>
>       status = beiscsi_create_eqs(phba, phwi_context);
>       if (status != 0) {
> @@ -5545,6 +5533,7 @@ static void beiscsi_eeh_resume(struct pci_dev
*pdev)
>       }
>
>       beiscsi_get_params(phba);
> +
>       phba->shost->max_id = phba->params.cxns_per_ctrl;
>       phba->shost->can_queue = phba->params.ios_per_ctrl;
>       ret = hwi_init_controller(phba);
> @@ -5681,6 +5670,8 @@ static int beiscsi_dev_probe(struct pci_dev
*pcidev,
>                           "BM_%d : Error getting fw config\n");
>               goto free_port;
>       }
> +     mgmt_get_port_name(&phba->ctrl, phba);
> +     beiscsi_get_params(phba);
>
>       if (enable_msix)
>               find_num_cpus(phba);
> @@ -5698,7 +5689,6 @@ static int beiscsi_dev_probe(struct pci_dev
*pcidev,
>       }
>
>       phba->shost->max_id = phba->params.cxns_per_ctrl;
> -     beiscsi_get_params(phba);
>       phba->shost->can_queue = phba->params.ios_per_ctrl;
>       ret = beiscsi_init_port(phba);
>       if (ret < 0) {
> diff --git a/drivers/scsi/be2iscsi/be_main.h
> b/drivers/scsi/be2iscsi/be_main.h index bd9d1e1..f89861b 100644
> --- a/drivers/scsi/be2iscsi/be_main.h
> +++ b/drivers/scsi/be2iscsi/be_main.h
> @@ -397,7 +397,9 @@ struct beiscsi_hba {
>                * group together since they are used most frequently
>                * for cid to cri conversion
>                */
> +#define BEISCSI_PHYS_PORT_MAX        4
>               unsigned int phys_port;
> +             /* valid values of phys_port id are 0, 1, 2, 3 */
>               unsigned int eqid_count;
>               unsigned int cqid_count;
>               unsigned int iscsi_cid_start[BEISCSI_ULP_COUNT];
> @@ -415,6 +417,7 @@ struct beiscsi_hba {
>       } fw_config;
>
>       unsigned int state;
> +     u8 optic_state;
>       int get_boot;
>       bool fw_timeout;
>       bool ue_detected;
> @@ -422,6 +425,7 @@ struct beiscsi_hba {
>
>       bool mac_addr_set;
>       u8 mac_address[ETH_ALEN];
> +     u8 port_name;
>       char fw_ver_str[BEISCSI_VER_STRLEN];
>       char wq_name[20];
>       struct workqueue_struct *wq;    /* The actuak work queue */
> @@ -1073,12 +1077,14 @@ struct hwi_context_memory {
>   #define BEISCSI_LOG_CONFIG  0x0020  /* CONFIG Code Path */
>   #define BEISCSI_LOG_ISCSI   0x0040  /* SCSI/iSCSI Protocol related
Logs */
>
> +#define __beiscsi_log(phba, level, fmt, arg...) \
> +     shost_printk(level, phba->shost, fmt, __LINE__, ##arg)
> +
>   #define beiscsi_log(phba, level, mask, fmt, arg...) \
>   do { \
>       uint32_t log_value = phba->attr_log_enable; \
>               if (((mask) & log_value) || (level[1] <= '3')) \
> -                     shost_printk(level, phba->shost, \
> -                                  fmt, __LINE__, ##arg); \
> -} while (0)
> +                     __beiscsi_log(phba, level, fmt, ##arg); \ } while
(0);
>
>   #endif
> diff --git a/drivers/scsi/be2iscsi/be_mgmt.c
> b/drivers/scsi/be2iscsi/be_mgmt.c index a8a1670..15f7ad7 100644
> --- a/drivers/scsi/be2iscsi/be_mgmt.c
> +++ b/drivers/scsi/be2iscsi/be_mgmt.c
> @@ -316,6 +316,48 @@ unsigned int mgmt_get_session_info(struct
beiscsi_hba *phba,
>   }
>
>   /**
> + * mgmt_get_port_name()- Get port name for the function
> + * @ctrl: ptr to Ctrl Info
> + * @phba: ptr to the dev priv structure
> + *
> + * Get the alphanumeric character for port
> + *
> + **/
> +int mgmt_get_port_name(struct be_ctrl_info *ctrl,
> +                    struct beiscsi_hba *phba)
> +{
> +     int ret = 0;
> +     struct be_mcc_wrb *wrb;
> +     struct be_cmd_get_port_name *ioctl;
> +
> +     mutex_lock(&ctrl->mbox_lock);
> +     wrb = wrb_from_mbox(&ctrl->mbox_mem);
> +     memset(wrb, 0, sizeof(*wrb));
> +     ioctl = embedded_payload(wrb);
> +
> +     be_wrb_hdr_prepare(wrb, sizeof(*ioctl), true, 0);
> +     be_cmd_hdr_prepare(&ioctl->h.req_hdr, CMD_SUBSYSTEM_COMMON,
> +                        OPCODE_COMMON_GET_PORT_NAME,
> +                        EMBED_MBX_MAX_PAYLOAD_SIZE);
> +     ret = be_mbox_notify(ctrl);
> +     phba->port_name = 0;
> +     if (!ret) {
> +             phba->port_name = ioctl->p.resp.port_names >>
> +                               (phba->fw_config.phys_port * 8) & 0xff;
> +     } else {
> +             beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
> +                         "BG_%d : GET_PORT_NAME ret 0x%x status
0x%x\n",
> +                         ret, ioctl->h.resp_hdr.status);
> +     }
> +
> +     if (phba->port_name == 0)
> +             phba->port_name = '?';
> +
> +     mutex_unlock(&ctrl->mbox_lock);
> +     return ret;
> +}
> +
> +/**
>    * mgmt_get_fw_config()- Get the FW config for the function
>    * @ctrl: ptr to Ctrl Info
>    * @phba: ptr to the dev priv structure @@ -331,90 +373,142 @@ int
> mgmt_get_fw_config(struct be_ctrl_info *ctrl,
>                               struct beiscsi_hba *phba)
>   {
>       struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
> -     struct be_fw_cfg *req = embedded_payload(wrb);
> -     int status = 0;
> +     struct be_fw_cfg *pfw_cfg = embedded_payload(wrb);
> +     uint32_t cid_count, icd_count;
> +     int status = -EINVAL;
> +     uint8_t ulp_num = 0;
>
>       mutex_lock(&ctrl->mbox_lock);
>       memset(wrb, 0, sizeof(*wrb));
> +     be_wrb_hdr_prepare(wrb, sizeof(*pfw_cfg), true, 0);
>
> -     be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
> -
> -     be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
> +     be_cmd_hdr_prepare(&pfw_cfg->hdr, CMD_SUBSYSTEM_COMMON,
>                          OPCODE_COMMON_QUERY_FIRMWARE_CONFIG,
>                          EMBED_MBX_MAX_PAYLOAD_SIZE);
> -     status = be_mbox_notify(ctrl);
> -     if (!status) {
> -             uint8_t ulp_num = 0;
> -             struct be_fw_cfg *pfw_cfg;
> -             pfw_cfg = req;
>
> -             if (!is_chip_be2_be3r(phba)) {
> -                     phba->fw_config.eqid_count = pfw_cfg->eqid_count;
> -                     phba->fw_config.cqid_count = pfw_cfg->cqid_count;
> +     if (be_mbox_notify(ctrl)) {
> +             beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
> +                         "BG_%d : Failed in mgmt_get_fw_config\n");
> +             goto fail_init;
> +     }
>
> -                     beiscsi_log(phba, KERN_INFO,
> -                                 BEISCSI_LOG_INIT,
> -                                 "BG_%d : EQ_Count : %d CQ_Count :
%d\n",
> -                                 phba->fw_config.eqid_count,
> +     /* FW response formats depend on port id */
> +     phba->fw_config.phys_port = pfw_cfg->phys_port;
> +     if (phba->fw_config.phys_port >= BEISCSI_PHYS_PORT_MAX) {
> +             beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
> +                         "BG_%d : invalid physical port id %d\n",
> +                         phba->fw_config.phys_port);
> +             goto fail_init;
> +     }
> +
> +     /* populate and check FW config against min and max values */
> +     if (!is_chip_be2_be3r(phba)) {
> +             phba->fw_config.eqid_count = pfw_cfg->eqid_count;
> +             phba->fw_config.cqid_count = pfw_cfg->cqid_count;
> +             if (phba->fw_config.eqid_count == 0 ||
> +                 phba->fw_config.eqid_count > 2048) {
> +                     beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
> +                                 "BG_%d : invalid EQ count %d\n",
> +                                 phba->fw_config.eqid_count);
> +                     goto fail_init;
> +             }
> +             if (phba->fw_config.cqid_count == 0 ||
> +                 phba->fw_config.cqid_count > 4096) {
> +                     beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
> +                                 "BG_%d : invalid CQ count %d\n",
>                                   phba->fw_config.cqid_count);
> +                     goto fail_init;
>               }
> +             beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
> +                         "BG_%d : EQ_Count : %d CQ_Count : %d\n",
> +                         phba->fw_config.eqid_count,
> +                         phba->fw_config.cqid_count);
> +     }
>
> -             for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++)
> -                     if (pfw_cfg->ulp[ulp_num].ulp_mode &
> -                         BEISCSI_ULP_ISCSI_INI_MODE)
> -                             set_bit(ulp_num,
> -                             &phba->fw_config.ulp_supported);
> -
> -             phba->fw_config.phys_port = pfw_cfg->phys_port;
> -             for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++)
{
> -                     if (test_bit(ulp_num,
&phba->fw_config.ulp_supported)) {
> -
> -                             phba->fw_config.iscsi_cid_start[ulp_num] =
> -                                     pfw_cfg->ulp[ulp_num].sq_base;
> -                             phba->fw_config.iscsi_cid_count[ulp_num] =
> -                                     pfw_cfg->ulp[ulp_num].sq_count;
> -
> -                             phba->fw_config.iscsi_icd_start[ulp_num] =
> -                                     pfw_cfg->ulp[ulp_num].icd_base;
> -                             phba->fw_config.iscsi_icd_count[ulp_num] =
> -                                     pfw_cfg->ulp[ulp_num].icd_count;
> -
> -                             phba->fw_config.iscsi_chain_start[ulp_num]
=
> -
pfw_cfg->chain_icd[ulp_num].chain_base;
> -                             phba->fw_config.iscsi_chain_count[ulp_num]
=
> -
pfw_cfg->chain_icd[ulp_num].chain_count;
> -
> -                             beiscsi_log(phba, KERN_INFO,
BEISCSI_LOG_INIT,
> -                                         "BG_%d : Function loaded on
ULP : %d\n"
> -                                         "\tiscsi_cid_count : %d\n"
> -                                         "\tiscsi_cid_start : %d\n"
> -                                         "\t iscsi_icd_count : %d\n"
> -                                         "\t iscsi_icd_start : %d\n",
> -                                         ulp_num,
> -                                         phba->fw_config.
> -                                         iscsi_cid_count[ulp_num],
> -                                         phba->fw_config.
> -                                         iscsi_cid_start[ulp_num],
> -                                         phba->fw_config.
> -                                         iscsi_icd_count[ulp_num],
> -                                         phba->fw_config.
> -                                         iscsi_icd_start[ulp_num]);
> -                     }
> +     /**
> +      * Check on which all ULP iSCSI Protocol is loaded.
> +      * Set the Bit for those ULP. This set flag is used
> +      * at all places in the code to check on which ULP
> +      * iSCSi Protocol is loaded
> +      **/
> +     for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) {
> +             if (pfw_cfg->ulp[ulp_num].ulp_mode &
> +                 BEISCSI_ULP_ISCSI_INI_MODE) {
> +                     set_bit(ulp_num, &phba->fw_config.ulp_supported);
> +
> +                     /* Get the CID, ICD and Chain count for each ULP
*/
> +                     phba->fw_config.iscsi_cid_start[ulp_num] =
> +                             pfw_cfg->ulp[ulp_num].sq_base;
> +                     phba->fw_config.iscsi_cid_count[ulp_num] =
> +                             pfw_cfg->ulp[ulp_num].sq_count;
> +
> +                     phba->fw_config.iscsi_icd_start[ulp_num] =
> +                             pfw_cfg->ulp[ulp_num].icd_base;
> +                     phba->fw_config.iscsi_icd_count[ulp_num] =
> +                             pfw_cfg->ulp[ulp_num].icd_count;
> +
> +                     phba->fw_config.iscsi_chain_start[ulp_num] =
> +                             pfw_cfg->chain_icd[ulp_num].chain_base;
> +                     phba->fw_config.iscsi_chain_count[ulp_num] =
> +                             pfw_cfg->chain_icd[ulp_num].chain_count;
> +
> +                     beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
> +                                 "BG_%d : Function loaded on ULP :
%d\n"
> +                                 "\tiscsi_cid_count : %d\n"
> +                                 "\tiscsi_cid_start : %d\n"
> +                                 "\t iscsi_icd_count : %d\n"
> +                                 "\t iscsi_icd_start : %d\n",
> +                                 ulp_num,
> +                                 phba->fw_config.
> +                                 iscsi_cid_count[ulp_num],
> +                                 phba->fw_config.
> +                                 iscsi_cid_start[ulp_num],
> +                                 phba->fw_config.
> +                                 iscsi_icd_count[ulp_num],
> +                                 phba->fw_config.
> +                                 iscsi_icd_start[ulp_num]);
>               }
> +     }
>
> -             phba->fw_config.dual_ulp_aware = (pfw_cfg->function_mode &
> -                                               BEISCSI_FUNC_DUA_MODE);
> +     if (phba->fw_config.ulp_supported == 0) {
> +             beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
> +                         "BG_%d : iSCSI initiator mode not set: ULP0 %x
ULP1 %x\n",
> +                         pfw_cfg->ulp[BEISCSI_ULP0].ulp_mode,
> +                         pfw_cfg->ulp[BEISCSI_ULP1].ulp_mode);
> +             goto fail_init;
> +     }
>
> -             beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
> -                         "BG_%d : DUA Mode : 0x%x\n",
> -                         phba->fw_config.dual_ulp_aware);
> +     /**
> +      * ICD is shared among ULPs. Use icd_count of any one loaded ULP
> +      **/
> +     for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++)
> +             if (test_bit(ulp_num, &phba->fw_config.ulp_supported))
> +                     break;
> +     icd_count = phba->fw_config.iscsi_icd_count[ulp_num];
> +     if (icd_count == 0 || icd_count > 65536) {
> +             beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
> +                         "BG_%d: invalid ICD count %d\n", icd_count);
> +             goto fail_init;
> +     }
>
> -     } else {
> +     cid_count = BEISCSI_GET_CID_COUNT(phba, BEISCSI_ULP0) +
> +                 BEISCSI_GET_CID_COUNT(phba, BEISCSI_ULP1);
> +     if (cid_count == 0 || cid_count > 4096) {
>               beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
> -                         "BG_%d : Failed in mgmt_get_fw_config\n");
> -             status = -EINVAL;
> +                         "BG_%d: invalid CID count %d\n", cid_count);
> +             goto fail_init;
>       }
>
> +     phba->fw_config.dual_ulp_aware = (pfw_cfg->function_mode &
> +                                       BEISCSI_FUNC_DUA_MODE);
> +
> +     beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
> +                 "BG_%d : DUA Mode : 0x%x\n",
> +                 phba->fw_config.dual_ulp_aware);
> +
> +     /* all set, continue using this FW config */
> +     status = 0;
> +fail_init:
>       mutex_unlock(&ctrl->mbox_lock);
>       return status;
>   }
> diff --git a/drivers/scsi/be2iscsi/be_mgmt.h
> b/drivers/scsi/be2iscsi/be_mgmt.h index c1dbb69..f3a48a0 100644
> --- a/drivers/scsi/be2iscsi/be_mgmt.h
> +++ b/drivers/scsi/be2iscsi/be_mgmt.h
> @@ -268,6 +268,8 @@ struct beiscsi_endpoint {
>
>   int mgmt_get_fw_config(struct be_ctrl_info *ctrl,
>                                struct beiscsi_hba *phba);
> +int mgmt_get_port_name(struct be_ctrl_info *ctrl,
> +                    struct beiscsi_hba *phba);
>
>   unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba,
>                                        struct beiscsi_endpoint
*beiscsi_ep,
>
Same goes for the firmware config validation.
Please move that to a separate patch.

Cheers,

Hannes
--
Dr. Hannes Reinecke                            zSeries & Storage
h...@suse.de                                   +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284
(AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to