Commit e59058c4 authored by James Smart's avatar James Smart Committed by James Bottomley

[SCSI] lpfc 8.2.8 : Add kernel-doc function headers

Signed-off-by: default avatarJames Smart <james.smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent 4a27446f
...@@ -49,6 +49,21 @@ ...@@ -49,6 +49,21 @@
#define LPFC_LINK_SPEED_BITMAP 0x00000117 #define LPFC_LINK_SPEED_BITMAP 0x00000117
#define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8" #define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8"
/**
* lpfc_jedec_to_ascii: Hex to ascii convertor according to JEDEC rules.
* @incr: integer to convert.
* @hdw: ascii string holding converted integer plus a string terminator.
*
* Description:
* JEDEC Joint Electron Device Engineering Council.
* Convert a 32 bit integer composed of 8 nibbles into an 8 byte ascii
* character string. The string is then terminated with a NULL in byte 9.
* Hex 0-9 becomes ascii '0' to '9'.
* Hex a-f becomes ascii '=' to 'B' capital B.
*
* Notes:
* Coded for 32 bit integers only.
**/
static void static void
lpfc_jedec_to_ascii(int incr, char hdw[]) lpfc_jedec_to_ascii(int incr, char hdw[])
{ {
...@@ -65,6 +80,14 @@ lpfc_jedec_to_ascii(int incr, char hdw[]) ...@@ -65,6 +80,14 @@ lpfc_jedec_to_ascii(int incr, char hdw[])
return; return;
} }
/**
* lpfc_drvr_version_show: Return the Emulex driver string with version number.
* @dev: class unused variable.
* @attr: device attribute, not used.
* @buf: on return contains the module description text.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_drvr_version_show(struct device *dev, struct device_attribute *attr, lpfc_drvr_version_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -72,6 +95,14 @@ lpfc_drvr_version_show(struct device *dev, struct device_attribute *attr, ...@@ -72,6 +95,14 @@ lpfc_drvr_version_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, LPFC_MODULE_DESC "\n"); return snprintf(buf, PAGE_SIZE, LPFC_MODULE_DESC "\n");
} }
/**
* lpfc_info_show: Return some pci info about the host in ascii.
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the formatted text from lpfc_info().
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_info_show(struct device *dev, struct device_attribute *attr, lpfc_info_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -81,6 +112,14 @@ lpfc_info_show(struct device *dev, struct device_attribute *attr, ...@@ -81,6 +112,14 @@ lpfc_info_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%s\n",lpfc_info(host)); return snprintf(buf, PAGE_SIZE, "%s\n",lpfc_info(host));
} }
/**
* lpfc_serialnum_show: Return the hba serial number in ascii.
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the formatted text serial number.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_serialnum_show(struct device *dev, struct device_attribute *attr, lpfc_serialnum_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -92,6 +131,18 @@ lpfc_serialnum_show(struct device *dev, struct device_attribute *attr, ...@@ -92,6 +131,18 @@ lpfc_serialnum_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%s\n",phba->SerialNumber); return snprintf(buf, PAGE_SIZE, "%s\n",phba->SerialNumber);
} }
/**
* lpfc_temp_sensor_show: Return the temperature sensor level.
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the formatted support level.
*
* Description:
* Returns a number indicating the temperature sensor level currently
* supported, zero or one in ascii.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_temp_sensor_show(struct device *dev, struct device_attribute *attr, lpfc_temp_sensor_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -102,6 +153,14 @@ lpfc_temp_sensor_show(struct device *dev, struct device_attribute *attr, ...@@ -102,6 +153,14 @@ lpfc_temp_sensor_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%d\n",phba->temp_sensor_support); return snprintf(buf, PAGE_SIZE, "%d\n",phba->temp_sensor_support);
} }
/**
* lpfc_modeldesc_show: Return the model description of the hba.
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the scsi vpd model description.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_modeldesc_show(struct device *dev, struct device_attribute *attr, lpfc_modeldesc_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -113,6 +172,14 @@ lpfc_modeldesc_show(struct device *dev, struct device_attribute *attr, ...@@ -113,6 +172,14 @@ lpfc_modeldesc_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelDesc); return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelDesc);
} }
/**
* lpfc_modelname_show: Return the model name of the hba.
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the scsi vpd model name.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_modelname_show(struct device *dev, struct device_attribute *attr, lpfc_modelname_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -124,6 +191,14 @@ lpfc_modelname_show(struct device *dev, struct device_attribute *attr, ...@@ -124,6 +191,14 @@ lpfc_modelname_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelName); return snprintf(buf, PAGE_SIZE, "%s\n",phba->ModelName);
} }
/**
* lpfc_programtype_show: Return the program type of the hba.
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the scsi vpd program type.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_programtype_show(struct device *dev, struct device_attribute *attr, lpfc_programtype_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -135,6 +210,14 @@ lpfc_programtype_show(struct device *dev, struct device_attribute *attr, ...@@ -135,6 +210,14 @@ lpfc_programtype_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%s\n",phba->ProgramType); return snprintf(buf, PAGE_SIZE, "%s\n",phba->ProgramType);
} }
/**
* lpfc_vportnum_show: Return the port number in ascii of the hba.
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains scsi vpd program type.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_vportnum_show(struct device *dev, struct device_attribute *attr, lpfc_vportnum_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -146,6 +229,14 @@ lpfc_vportnum_show(struct device *dev, struct device_attribute *attr, ...@@ -146,6 +229,14 @@ lpfc_vportnum_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%s\n",phba->Port); return snprintf(buf, PAGE_SIZE, "%s\n",phba->Port);
} }
/**
* lpfc_fwrev_show: Return the firmware rev running in the hba.
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the scsi vpd program type.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_fwrev_show(struct device *dev, struct device_attribute *attr, lpfc_fwrev_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -159,6 +250,14 @@ lpfc_fwrev_show(struct device *dev, struct device_attribute *attr, ...@@ -159,6 +250,14 @@ lpfc_fwrev_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%s, sli-%d\n", fwrev, phba->sli_rev); return snprintf(buf, PAGE_SIZE, "%s, sli-%d\n", fwrev, phba->sli_rev);
} }
/**
* lpfc_hdw_show: Return the jedec information about the hba.
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the scsi vpd program type.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_hdw_show(struct device *dev, struct device_attribute *attr, char *buf) lpfc_hdw_show(struct device *dev, struct device_attribute *attr, char *buf)
{ {
...@@ -171,6 +270,15 @@ lpfc_hdw_show(struct device *dev, struct device_attribute *attr, char *buf) ...@@ -171,6 +270,15 @@ lpfc_hdw_show(struct device *dev, struct device_attribute *attr, char *buf)
lpfc_jedec_to_ascii(vp->rev.biuRev, hdw); lpfc_jedec_to_ascii(vp->rev.biuRev, hdw);
return snprintf(buf, PAGE_SIZE, "%s\n", hdw); return snprintf(buf, PAGE_SIZE, "%s\n", hdw);
} }
/**
* lpfc_option_rom_version_show: Return the adapter ROM FCode version.
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the ROM and FCode ascii strings.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_option_rom_version_show(struct device *dev, struct device_attribute *attr, lpfc_option_rom_version_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -181,6 +289,18 @@ lpfc_option_rom_version_show(struct device *dev, struct device_attribute *attr, ...@@ -181,6 +289,18 @@ lpfc_option_rom_version_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%s\n", phba->OptionROMVersion); return snprintf(buf, PAGE_SIZE, "%s\n", phba->OptionROMVersion);
} }
/**
* lpfc_state_show: Return the link state of the port.
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains text describing the state of the link.
*
* Notes:
* The switch statement has no default so zero will be returned.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_link_state_show(struct device *dev, struct device_attribute *attr, lpfc_link_state_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -253,6 +373,18 @@ lpfc_link_state_show(struct device *dev, struct device_attribute *attr, ...@@ -253,6 +373,18 @@ lpfc_link_state_show(struct device *dev, struct device_attribute *attr,
return len; return len;
} }
/**
* lpfc_num_discovered_ports_show: Return sum of mapped and unmapped vports.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the sum of fc mapped and unmapped.
*
* Description:
* Returns the ascii text number of the sum of the fc mapped and unmapped
* vport counts.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_num_discovered_ports_show(struct device *dev, lpfc_num_discovered_ports_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
...@@ -264,7 +396,20 @@ lpfc_num_discovered_ports_show(struct device *dev, ...@@ -264,7 +396,20 @@ lpfc_num_discovered_ports_show(struct device *dev,
vport->fc_map_cnt + vport->fc_unmap_cnt); vport->fc_map_cnt + vport->fc_unmap_cnt);
} }
/**
* lpfc_issue_lip: Misnomer, name carried over from long ago.
* @shost: Scsi_Host pointer.
*
* Description:
* Bring the link down gracefully then re-init the link. The firmware will
* re-init the fiber channel interface as required. Does not issue a LIP.
*
* Returns:
* -EPERM port offline or management commands are being blocked
* -ENOMEM cannot allocate memory for the mailbox command
* -EIO error sending the mailbox command
* zero for success
**/
static int static int
lpfc_issue_lip(struct Scsi_Host *shost) lpfc_issue_lip(struct Scsi_Host *shost)
{ {
...@@ -306,6 +451,21 @@ lpfc_issue_lip(struct Scsi_Host *shost) ...@@ -306,6 +451,21 @@ lpfc_issue_lip(struct Scsi_Host *shost)
return 0; return 0;
} }
/**
* lpfc_do_offline: Issues a mailbox command to bring the link down.
* @phba: lpfc_hba pointer.
* @type: LPFC_EVT_OFFLINE, LPFC_EVT_WARM_START, LPFC_EVT_KILL.
*
* Notes:
* Assumes any error from lpfc_do_offline() will be negative.
* Can wait up to 5 seconds for the port ring buffers count
* to reach zero, prints a warning if it is not zero and continues.
* lpfc_workq_post_event() returns a non-zero return coce if call fails.
*
* Returns:
* -EIO error posting the event
* zero for success
**/
static int static int
lpfc_do_offline(struct lpfc_hba *phba, uint32_t type) lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
{ {
...@@ -353,6 +513,22 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type) ...@@ -353,6 +513,22 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
return 0; return 0;
} }
/**
* lpfc_selective_reset: Offline then onlines the port.
* @phba: lpfc_hba pointer.
*
* Description:
* If the port is configured to allow a reset then the hba is brought
* offline then online.
*
* Notes:
* Assumes any error from lpfc_do_offline() will be negative.
*
* Returns:
* lpfc_do_offline() return code if not zero
* -EIO reset not configured or error posting the event
* zero for success
**/
static int static int
lpfc_selective_reset(struct lpfc_hba *phba) lpfc_selective_reset(struct lpfc_hba *phba)
{ {
...@@ -378,6 +554,27 @@ lpfc_selective_reset(struct lpfc_hba *phba) ...@@ -378,6 +554,27 @@ lpfc_selective_reset(struct lpfc_hba *phba)
return 0; return 0;
} }
/**
* lpfc_issue_reset: Selectively resets an adapter.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: containing the string "selective".
* @count: unused variable.
*
* Description:
* If the buf contains the string "selective" then lpfc_selective_reset()
* is called to perform the reset.
*
* Notes:
* Assumes any error from lpfc_selective_reset() will be negative.
* If lpfc_selective_reset() returns zero then the length of the buffer
* is returned which indicates succcess
*
* Returns:
* -EINVAL if the buffer does not contain the string "selective"
* length of buf if lpfc-selective_reset() if the call succeeds
* return value of lpfc_selective_reset() if the call fails
**/
static ssize_t static ssize_t
lpfc_issue_reset(struct device *dev, struct device_attribute *attr, lpfc_issue_reset(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
...@@ -397,6 +594,14 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr, ...@@ -397,6 +594,14 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr,
return status; return status;
} }
/**
* lpfc_nport_evt_cnt_show: Return the number of nport events.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the ascii number of nport events.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_nport_evt_cnt_show(struct device *dev, struct device_attribute *attr, lpfc_nport_evt_cnt_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -408,6 +613,14 @@ lpfc_nport_evt_cnt_show(struct device *dev, struct device_attribute *attr, ...@@ -408,6 +613,14 @@ lpfc_nport_evt_cnt_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%d\n", phba->nport_event_cnt); return snprintf(buf, PAGE_SIZE, "%d\n", phba->nport_event_cnt);
} }
/**
* lpfc_board_mode_show: Return the state of the board.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the state of the adapter.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_board_mode_show(struct device *dev, struct device_attribute *attr, lpfc_board_mode_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -429,6 +642,19 @@ lpfc_board_mode_show(struct device *dev, struct device_attribute *attr, ...@@ -429,6 +642,19 @@ lpfc_board_mode_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%s\n", state); return snprintf(buf, PAGE_SIZE, "%s\n", state);
} }
/**
* lpfc_board_mode_store: Puts the hba in online, offline, warm or error state.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: containing one of the strings "online", "offline", "warm" or "error".
* @count: unused variable.
*
* Returns:
* -EACCES if enable hba reset not enabled
* -EINVAL if the buffer does not contain a valid string (see above)
* -EIO if lpfc_workq_post_event() or lpfc_do_offline() fails
* buf length greater than zero indicates success
**/
static ssize_t static ssize_t
lpfc_board_mode_store(struct device *dev, struct device_attribute *attr, lpfc_board_mode_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
...@@ -462,6 +688,24 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr, ...@@ -462,6 +688,24 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr,
return -EIO; return -EIO;
} }
/**
* lpfc_get_hba_info: Return various bits of informaton about the adapter.
* @phba: pointer to the adapter structure.
* @mxri max xri count.
* @axri available xri count.
* @mrpi max rpi count.
* @arpi available rpi count.
* @mvpi max vpi count.
* @avpi available vpi count.
*
* Description:
* If an integer pointer for an count is not null then the value for the
* count is returned.
*
* Returns:
* zero on error
* one for success
**/
static int static int
lpfc_get_hba_info(struct lpfc_hba *phba, lpfc_get_hba_info(struct lpfc_hba *phba,
uint32_t *mxri, uint32_t *axri, uint32_t *mxri, uint32_t *axri,
...@@ -524,6 +768,20 @@ lpfc_get_hba_info(struct lpfc_hba *phba, ...@@ -524,6 +768,20 @@ lpfc_get_hba_info(struct lpfc_hba *phba,
return 1; return 1;
} }
/**
* lpfc_max_rpi_show: Return maximum rpi.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the maximum rpi count in decimal or "Unknown".
*
* Description:
* Calls lpfc_get_hba_info() asking for just the mrpi count.
* If lpfc_get_hba_info() returns zero (failure) the buffer text is set
* to "Unknown" and the buffer length is returned, therefore the caller
* must check for "Unknown" in the buffer to detect a failure.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_max_rpi_show(struct device *dev, struct device_attribute *attr, lpfc_max_rpi_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -538,6 +796,20 @@ lpfc_max_rpi_show(struct device *dev, struct device_attribute *attr, ...@@ -538,6 +796,20 @@ lpfc_max_rpi_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "Unknown\n"); return snprintf(buf, PAGE_SIZE, "Unknown\n");
} }
/**
* lpfc_used_rpi_show: Return maximum rpi minus available rpi.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: containing the used rpi count in decimal or "Unknown".
*
* Description:
* Calls lpfc_get_hba_info() asking for just the mrpi and arpi counts.
* If lpfc_get_hba_info() returns zero (failure) the buffer text is set
* to "Unknown" and the buffer length is returned, therefore the caller
* must check for "Unknown" in the buffer to detect a failure.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_used_rpi_show(struct device *dev, struct device_attribute *attr, lpfc_used_rpi_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -552,6 +824,20 @@ lpfc_used_rpi_show(struct device *dev, struct device_attribute *attr, ...@@ -552,6 +824,20 @@ lpfc_used_rpi_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "Unknown\n"); return snprintf(buf, PAGE_SIZE, "Unknown\n");
} }
/**
* lpfc_max_xri_show: Return maximum xri.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the maximum xri count in decimal or "Unknown".
*
* Description:
* Calls lpfc_get_hba_info() asking for just the mrpi count.
* If lpfc_get_hba_info() returns zero (failure) the buffer text is set
* to "Unknown" and the buffer length is returned, therefore the caller
* must check for "Unknown" in the buffer to detect a failure.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_max_xri_show(struct device *dev, struct device_attribute *attr, lpfc_max_xri_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -566,6 +852,20 @@ lpfc_max_xri_show(struct device *dev, struct device_attribute *attr, ...@@ -566,6 +852,20 @@ lpfc_max_xri_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "Unknown\n"); return snprintf(buf, PAGE_SIZE, "Unknown\n");
} }
/**
* lpfc_used_xri_show: Return maximum xpi minus the available xpi.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the used xri count in decimal or "Unknown".
*
* Description:
* Calls lpfc_get_hba_info() asking for just the mxri and axri counts.
* If lpfc_get_hba_info() returns zero (failure) the buffer text is set
* to "Unknown" and the buffer length is returned, therefore the caller
* must check for "Unknown" in the buffer to detect a failure.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_used_xri_show(struct device *dev, struct device_attribute *attr, lpfc_used_xri_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -580,6 +880,20 @@ lpfc_used_xri_show(struct device *dev, struct device_attribute *attr, ...@@ -580,6 +880,20 @@ lpfc_used_xri_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "Unknown\n"); return snprintf(buf, PAGE_SIZE, "Unknown\n");
} }
/**
* lpfc_max_vpi_show: Return maximum vpi.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the maximum vpi count in decimal or "Unknown".
*
* Description:
* Calls lpfc_get_hba_info() asking for just the mvpi count.
* If lpfc_get_hba_info() returns zero (failure) the buffer text is set
* to "Unknown" and the buffer length is returned, therefore the caller
* must check for "Unknown" in the buffer to detect a failure.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_max_vpi_show(struct device *dev, struct device_attribute *attr, lpfc_max_vpi_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -594,6 +908,20 @@ lpfc_max_vpi_show(struct device *dev, struct device_attribute *attr, ...@@ -594,6 +908,20 @@ lpfc_max_vpi_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "Unknown\n"); return snprintf(buf, PAGE_SIZE, "Unknown\n");
} }
/**
* lpfc_used_vpi_show: Return maximum vpi minus the available vpi.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the used vpi count in decimal or "Unknown".
*
* Description:
* Calls lpfc_get_hba_info() asking for just the mvpi and avpi counts.
* If lpfc_get_hba_info() returns zero (failure) the buffer text is set
* to "Unknown" and the buffer length is returned, therefore the caller
* must check for "Unknown" in the buffer to detect a failure.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_used_vpi_show(struct device *dev, struct device_attribute *attr, lpfc_used_vpi_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -608,6 +936,19 @@ lpfc_used_vpi_show(struct device *dev, struct device_attribute *attr, ...@@ -608,6 +936,19 @@ lpfc_used_vpi_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "Unknown\n"); return snprintf(buf, PAGE_SIZE, "Unknown\n");
} }
/**
* lpfc_npiv_info_show: Return text about NPIV support for the adapter.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: text that must be interpreted to determine if npiv is supported.
*
* Description:
* Buffer will contain text indicating npiv is not suppoerted on the port,
* the port is an NPIV physical port, or it is an npiv virtual port with
* the id of the vport.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_npiv_info_show(struct device *dev, struct device_attribute *attr, lpfc_npiv_info_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -623,6 +964,17 @@ lpfc_npiv_info_show(struct device *dev, struct device_attribute *attr, ...@@ -623,6 +964,17 @@ lpfc_npiv_info_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "NPIV Virtual (VPI %d)\n", vport->vpi); return snprintf(buf, PAGE_SIZE, "NPIV Virtual (VPI %d)\n", vport->vpi);
} }
/**
* lpfc_poll_show: Return text about poll support for the adapter.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the cfg_poll in hex.
*
* Notes:
* cfg_poll should be a lpfc_polling_flags type.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_poll_show(struct device *dev, struct device_attribute *attr, lpfc_poll_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -634,6 +986,20 @@ lpfc_poll_show(struct device *dev, struct device_attribute *attr, ...@@ -634,6 +986,20 @@ lpfc_poll_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%#x\n", phba->cfg_poll); return snprintf(buf, PAGE_SIZE, "%#x\n", phba->cfg_poll);
} }
/**
* lpfc_poll_store: Set the value of cfg_poll for the adapter.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: one or more lpfc_polling_flags values.
* @count: not used.
*
* Notes:
* buf contents converted to integer and checked for a valid value.
*
* Returns:
* -EINVAL if the buffer connot be converted or is out of range
* length of the buf on success
**/
static ssize_t static ssize_t
lpfc_poll_store(struct device *dev, struct device_attribute *attr, lpfc_poll_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
...@@ -692,6 +1058,20 @@ lpfc_poll_store(struct device *dev, struct device_attribute *attr, ...@@ -692,6 +1058,20 @@ lpfc_poll_store(struct device *dev, struct device_attribute *attr,
return strlen(buf); return strlen(buf);
} }
/**
* lpfc_param_show: Return a cfg attribute value in decimal.
*
* Description:
* Macro that given an attr e.g. hba_queue_depth expands
* into a function with the name lpfc_hba_queue_depth_show.
*
* lpfc_##attr##_show: Return the decimal value of an adapters cfg_xxx field.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the attribute value in decimal.
*
* Returns: size of formatted string.
**/
#define lpfc_param_show(attr) \ #define lpfc_param_show(attr) \
static ssize_t \ static ssize_t \
lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
...@@ -706,6 +1086,20 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ ...@@ -706,6 +1086,20 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
phba->cfg_##attr);\ phba->cfg_##attr);\
} }
/**
* lpfc_param_hex_show: Return a cfg attribute value in hex.
*
* Description:
* Macro that given an attr e.g. hba_queue_depth expands
* into a function with the name lpfc_hba_queue_depth_show
*
* lpfc_##attr##_show: Return the hex value of an adapters cfg_xxx field.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the attribute value in hexidecimal.
*
* Returns: size of formatted string.
**/
#define lpfc_param_hex_show(attr) \ #define lpfc_param_hex_show(attr) \
static ssize_t \ static ssize_t \
lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
...@@ -720,6 +1114,25 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ ...@@ -720,6 +1114,25 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
phba->cfg_##attr);\ phba->cfg_##attr);\
} }
/**
* lpfc_param_init: Intializes a cfg attribute.
*
* Description:
* Macro that given an attr e.g. hba_queue_depth expands
* into a function with the name lpfc_hba_queue_depth_init. The macro also
* takes a default argument, a minimum and maximum argument.
*
* lpfc_##attr##_init: Initializes an attribute.
* @phba: pointer the the adapter structure.
* @val: integer attribute value.
*
* Validates the min and max values then sets the adapter config field
* accordingly, or uses the default if out of range and prints an error message.
*
* Returns:
* zero on success
* -EINVAL if default used
**/
#define lpfc_param_init(attr, default, minval, maxval) \ #define lpfc_param_init(attr, default, minval, maxval) \
static int \ static int \
lpfc_##attr##_init(struct lpfc_hba *phba, int val) \ lpfc_##attr##_init(struct lpfc_hba *phba, int val) \
...@@ -735,6 +1148,26 @@ lpfc_##attr##_init(struct lpfc_hba *phba, int val) \ ...@@ -735,6 +1148,26 @@ lpfc_##attr##_init(struct lpfc_hba *phba, int val) \
return -EINVAL;\ return -EINVAL;\
} }
/**
* lpfc_param_set: Set a cfg attribute value.
*
* Description:
* Macro that given an attr e.g. hba_queue_depth expands
* into a function with the name lpfc_hba_queue_depth_set
*
* lpfc_##attr##_set: Sets an attribute value.
* @phba: pointer the the adapter structure.
* @val: integer attribute value.
*
* Description:
* Validates the min and max values then sets the
* adapter config field if in the valid range. prints error message
* and does not set the parameter if invalid.
*
* Returns:
* zero on success
* -EINVAL if val is invalid
**/
#define lpfc_param_set(attr, default, minval, maxval) \ #define lpfc_param_set(attr, default, minval, maxval) \
static int \ static int \
lpfc_##attr##_set(struct lpfc_hba *phba, int val) \ lpfc_##attr##_set(struct lpfc_hba *phba, int val) \
...@@ -749,6 +1182,27 @@ lpfc_##attr##_set(struct lpfc_hba *phba, int val) \ ...@@ -749,6 +1182,27 @@ lpfc_##attr##_set(struct lpfc_hba *phba, int val) \
return -EINVAL;\ return -EINVAL;\
} }
/**
* lpfc_param_store: Set a vport attribute value.
*
* Description:
* Macro that given an attr e.g. hba_queue_depth expands
* into a function with the name lpfc_hba_queue_depth_store.
*
* lpfc_##attr##_store: Set an sttribute value.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: contains the attribute value in ascii.
* @count: not used.
*
* Description:
* Convert the ascii text number to an integer, then
* use the lpfc_##attr##_set function to set the value.
*
* Returns:
* -EINVAL if val is invalid or lpfc_##attr##_set() fails
* length of buffer upon success.
**/
#define lpfc_param_store(attr) \ #define lpfc_param_store(attr) \
static ssize_t \ static ssize_t \
lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \ lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \
...@@ -768,6 +1222,20 @@ lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \ ...@@ -768,6 +1222,20 @@ lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \
return -EINVAL;\ return -EINVAL;\
} }
/**
* lpfc_vport_param_show: Return decimal formatted cfg attribute value.
*
* Description:
* Macro that given an attr e.g. hba_queue_depth expands
* into a function with the name lpfc_hba_queue_depth_show
*
* lpfc_##attr##_show: prints the attribute value in decimal.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the attribute value in decimal.
*
* Returns: length of formatted string.
**/
#define lpfc_vport_param_show(attr) \ #define lpfc_vport_param_show(attr) \
static ssize_t \ static ssize_t \
lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
...@@ -780,6 +1248,21 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ ...@@ -780,6 +1248,21 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
return snprintf(buf, PAGE_SIZE, "%d\n", vport->cfg_##attr);\ return snprintf(buf, PAGE_SIZE, "%d\n", vport->cfg_##attr);\
} }
/**
* lpfc_vport_param_hex_show: Return hex formatted attribute value.
*
* Description:
* Macro that given an attr e.g.
* hba_queue_depth expands into a function with the name
* lpfc_hba_queue_depth_show
*
* lpfc_##attr##_show: prints the attribute value in hexidecimal.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the attribute value in hexidecimal.
*
* Returns: length of formatted string.
**/
#define lpfc_vport_param_hex_show(attr) \ #define lpfc_vport_param_hex_show(attr) \
static ssize_t \ static ssize_t \
lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
...@@ -792,6 +1275,24 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ ...@@ -792,6 +1275,24 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
return snprintf(buf, PAGE_SIZE, "%#x\n", vport->cfg_##attr);\ return snprintf(buf, PAGE_SIZE, "%#x\n", vport->cfg_##attr);\
} }
/**
* lpfc_vport_param_init: Initialize a vport cfg attribute.
*
* Description:
* Macro that given an attr e.g. hba_queue_depth expands
* into a function with the name lpfc_hba_queue_depth_init. The macro also
* takes a default argument, a minimum and maximum argument.
*
* lpfc_##attr##_init: validates the min and max values then sets the
* adapter config field accordingly, or uses the default if out of range
* and prints an error message.
* @phba: pointer the the adapter structure.
* @val: integer attribute value.
*
* Returns:
* zero on success
* -EINVAL if default used
**/
#define lpfc_vport_param_init(attr, default, minval, maxval) \ #define lpfc_vport_param_init(attr, default, minval, maxval) \
static int \ static int \
lpfc_##attr##_init(struct lpfc_vport *vport, int val) \ lpfc_##attr##_init(struct lpfc_vport *vport, int val) \
...@@ -807,6 +1308,23 @@ lpfc_##attr##_init(struct lpfc_vport *vport, int val) \ ...@@ -807,6 +1308,23 @@ lpfc_##attr##_init(struct lpfc_vport *vport, int val) \
return -EINVAL;\ return -EINVAL;\
} }
/**
* lpfc_vport_param_set: Set a vport cfg attribute.
*
* Description:
* Macro that given an attr e.g. hba_queue_depth expands
* into a function with the name lpfc_hba_queue_depth_set
*
* lpfc_##attr##_set: validates the min and max values then sets the
* adapter config field if in the valid range. prints error message
* and does not set the parameter if invalid.
* @phba: pointer the the adapter structure.
* @val: integer attribute value.
*
* Returns:
* zero on success
* -EINVAL if val is invalid
**/
#define lpfc_vport_param_set(attr, default, minval, maxval) \ #define lpfc_vport_param_set(attr, default, minval, maxval) \
static int \ static int \
lpfc_##attr##_set(struct lpfc_vport *vport, int val) \ lpfc_##attr##_set(struct lpfc_vport *vport, int val) \
...@@ -821,6 +1339,23 @@ lpfc_##attr##_set(struct lpfc_vport *vport, int val) \ ...@@ -821,6 +1339,23 @@ lpfc_##attr##_set(struct lpfc_vport *vport, int val) \
return -EINVAL;\ return -EINVAL;\
} }
/**
* lpfc_vport_param_store: Set a vport attribute.
*
* Description:
* Macro that given an attr e.g. hba_queue_depth
* expands into a function with the name lpfc_hba_queue_depth_store
*
* lpfc_##attr##_store: convert the ascii text number to an integer, then
* use the lpfc_##attr##_set function to set the value.
* @cdev: class device that is converted into a Scsi_host.
* @buf: contains the attribute value in decimal.
* @count: not used.
*
* Returns:
* -EINVAL if val is invalid or lpfc_##attr##_set() fails
* length of buffer upon success.
**/
#define lpfc_vport_param_store(attr) \ #define lpfc_vport_param_store(attr) \
static ssize_t \ static ssize_t \
lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \ lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \
...@@ -958,6 +1493,17 @@ static DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show, NULL); ...@@ -958,6 +1493,17 @@ static DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show, NULL);
static char *lpfc_soft_wwn_key = "C99G71SL8032A"; static char *lpfc_soft_wwn_key = "C99G71SL8032A";
/**
* lpfc_soft_wwn_enable_store: Allows setting of the wwn if the key is valid.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: containing the string lpfc_soft_wwn_key.
* @count: must be size of lpfc_soft_wwn_key.
*
* Returns:
* -EINVAL if the buffer does not contain lpfc_soft_wwn_key
* length of buf indicates success
**/
static ssize_t static ssize_t
lpfc_soft_wwn_enable_store(struct device *dev, struct device_attribute *attr, lpfc_soft_wwn_enable_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
...@@ -994,6 +1540,14 @@ lpfc_soft_wwn_enable_store(struct device *dev, struct device_attribute *attr, ...@@ -994,6 +1540,14 @@ lpfc_soft_wwn_enable_store(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR(lpfc_soft_wwn_enable, S_IWUSR, NULL, static DEVICE_ATTR(lpfc_soft_wwn_enable, S_IWUSR, NULL,
lpfc_soft_wwn_enable_store); lpfc_soft_wwn_enable_store);
/**
* lpfc_soft_wwpn_show: Return the cfg soft ww port name of the adapter.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the wwpn in hexidecimal.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_soft_wwpn_show(struct device *dev, struct device_attribute *attr, lpfc_soft_wwpn_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -1006,7 +1560,19 @@ lpfc_soft_wwpn_show(struct device *dev, struct device_attribute *attr, ...@@ -1006,7 +1560,19 @@ lpfc_soft_wwpn_show(struct device *dev, struct device_attribute *attr,
(unsigned long long)phba->cfg_soft_wwpn); (unsigned long long)phba->cfg_soft_wwpn);
} }
/**
* lpfc_soft_wwpn_store: Set the ww port name of the adapter.
* @dev class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: contains the wwpn in hexidecimal.
* @count: number of wwpn bytes in buf
*
* Returns:
* -EACCES hba reset not enabled, adapter over temp
* -EINVAL soft wwn not enabled, count is invalid, invalid wwpn byte invalid
* -EIO error taking adapter offline or online
* value of count on success
**/
static ssize_t static ssize_t
lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr, lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
...@@ -1080,6 +1646,14 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr, ...@@ -1080,6 +1646,14 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\ static DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\
lpfc_soft_wwpn_show, lpfc_soft_wwpn_store); lpfc_soft_wwpn_show, lpfc_soft_wwpn_store);
/**
* lpfc_soft_wwnn_show: Return the cfg soft ww node name for the adapter.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the wwnn in hexidecimal.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_soft_wwnn_show(struct device *dev, struct device_attribute *attr, lpfc_soft_wwnn_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -1090,7 +1664,16 @@ lpfc_soft_wwnn_show(struct device *dev, struct device_attribute *attr, ...@@ -1090,7 +1664,16 @@ lpfc_soft_wwnn_show(struct device *dev, struct device_attribute *attr,
(unsigned long long)phba->cfg_soft_wwnn); (unsigned long long)phba->cfg_soft_wwnn);
} }
/**
* lpfc_soft_wwnn_store: sets the ww node name of the adapter.
* @cdev: class device that is converted into a Scsi_host.
* @buf: contains the ww node name in hexidecimal.
* @count: number of wwnn bytes in buf.
*
* Returns:
* -EINVAL soft wwn not enabled, count is invalid, invalid wwnn byte invalid
* value of count on success
**/
static ssize_t static ssize_t
lpfc_soft_wwnn_store(struct device *dev, struct device_attribute *attr, lpfc_soft_wwnn_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
...@@ -1178,6 +1761,15 @@ module_param(lpfc_nodev_tmo, int, 0); ...@@ -1178,6 +1761,15 @@ module_param(lpfc_nodev_tmo, int, 0);
MODULE_PARM_DESC(lpfc_nodev_tmo, MODULE_PARM_DESC(lpfc_nodev_tmo,
"Seconds driver will hold I/O waiting " "Seconds driver will hold I/O waiting "
"for a device to come back"); "for a device to come back");
/**
* lpfc_nodev_tmo_show: Return the hba dev loss timeout value.
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the dev loss timeout in decimal.
*
* Returns: size of formatted string.
**/
static ssize_t static ssize_t
lpfc_nodev_tmo_show(struct device *dev, struct device_attribute *attr, lpfc_nodev_tmo_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
...@@ -1189,6 +1781,21 @@ lpfc_nodev_tmo_show(struct device *dev, struct device_attribute *attr, ...@@ -1189,6 +1781,21 @@ lpfc_nodev_tmo_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%d\n", vport->cfg_devloss_tmo); return snprintf(buf, PAGE_SIZE, "%d\n", vport->cfg_devloss_tmo);
} }
/**
* lpfc_nodev_tmo_init: Set the hba nodev timeout value.
* @vport: lpfc vport structure pointer.
* @val: contains the nodev timeout value.
*
* Description:
* If the devloss tmo is already set then nodev tmo is set to devloss tmo,
* a kernel error message is printed and zero is returned.
* Else if val is in range then nodev tmo and devloss tmo are set to val.
* Otherwise nodev tmo is set to the default value.
*
* Returns:
* zero if already set or if val is in range
* -EINVAL val out of range
**/
static int static int
lpfc_nodev_tmo_init(struct lpfc_vport *vport, int val) lpfc_nodev_tmo_init(struct lpfc_vport *vport, int val)
{ {
...@@ -1215,6 +1822,13 @@ lpfc_nodev_tmo_init(struct lpfc_vport *vport, int val) ...@@ -1215,6 +1822,13 @@ lpfc_nodev_tmo_init(struct lpfc_vport *vport, int val)
return -EINVAL; return -EINVAL;
} }
/**
* lpfc_update_rport_devloss_tmo: Update dev loss tmo value.
* @vport: lpfc vport structure pointer.
*
* Description:
* Update all the ndlp's dev loss tmo with the vport devloss tmo value.
**/
static void static void
lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport) lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport)
{ {
...@@ -1229,6 +1843,21 @@ lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport) ...@@ -1229,6 +1843,21 @@ lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport)
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
} }
/**
* lpfc_nodev_tmo_set: Set the vport nodev tmo and devloss tmo values.
* @vport: lpfc vport structure pointer.
* @val: contains the tmo value.
*
* Description:
* If the devloss tmo is already set or the vport dev loss tmo has changed
* then a kernel error message is printed and zero is returned.
* Else if val is in range then nodev tmo and devloss tmo are set to val.
* Otherwise nodev tmo is set to the default value.
*
* Returns:
* zero if already set or if val is in range
* -EINVAL val out of range
**/
static int static int
lpfc_nodev_tmo_set(struct lpfc_vport *vport, int val) lpfc_nodev_tmo_set(struct lpfc_vport *vport, int val)
{ {
...@@ -1269,6 +1898,21 @@ MODULE_PARM_DESC(lpfc_devloss_tmo, ...@@ -1269,6 +1898,21 @@ MODULE_PARM_DESC(lpfc_devloss_tmo,
lpfc_vport_param_init(devloss_tmo, LPFC_DEF_DEVLOSS_TMO, lpfc_vport_param_init(devloss_tmo, LPFC_DEF_DEVLOSS_TMO,
LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO) LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO)
lpfc_vport_param_show(devloss_tmo) lpfc_vport_param_show(devloss_tmo)
/**
* lpfc_devloss_tmo_set: Sets vport nodev tmo, devloss tmo values, changed bit.
* @vport: lpfc vport structure pointer.
* @val: contains the tmo value.
*
* Description:
* If val is in a valid range then set the vport nodev tmo,
* devloss tmo, also set the vport dev loss tmo changed flag.
* Else a kernel error message is printed.
*
* Returns:
* zero if val is in range
* -EINVAL val out of range
**/
static int static int
lpfc_devloss_tmo_set(struct lpfc_vport *vport, int val) lpfc_devloss_tmo_set(struct lpfc_vport *vport, int val)
{ {
...@@ -1366,6 +2010,21 @@ MODULE_PARM_DESC(lpfc_restrict_login, ...@@ -1366,6 +2010,21 @@ MODULE_PARM_DESC(lpfc_restrict_login,
"Restrict virtual ports login to remote initiators."); "Restrict virtual ports login to remote initiators.");
lpfc_vport_param_show(restrict_login); lpfc_vport_param_show(restrict_login);
/**
* lpfc_restrict_login_init: Set the vport restrict login flag.
* @vport: lpfc vport structure pointer.
* @val: contains the restrict login value.
*
* Description:
* If val is not in a valid range then log a kernel error message and set
* the vport restrict login to one.
* If the port type is physical clear the restrict login flag and return.
* Else set the restrict login flag to val.
*
* Returns:
* zero if val is in range
* -EINVAL val out of range
**/
static int static int
lpfc_restrict_login_init(struct lpfc_vport *vport, int val) lpfc_restrict_login_init(struct lpfc_vport *vport, int val)
{ {
...@@ -1385,6 +2044,22 @@ lpfc_restrict_login_init(struct lpfc_vport *vport, int val) ...@@ -1385,6 +2044,22 @@ lpfc_restrict_login_init(struct lpfc_vport *vport, int val)
return 0; return 0;
} }
/**
* lpfc_restrict_login_set: Set the vport restrict login flag.
* @vport: lpfc vport structure pointer.
* @val: contains the restrict login value.
*
* Description:
* If val is not in a valid range then log a kernel error message and set
* the vport restrict login to one.
* If the port type is physical and the val is not zero log a kernel
* error message, clear the restrict login flag and return zero.
* Else set the restrict login flag to val.
*
* Returns:
* zero if val is in range
* -EINVAL val out of range
**/
static int static int
lpfc_restrict_login_set(struct lpfc_vport *vport, int val) lpfc_restrict_login_set(struct lpfc_vport *vport, int val)
{ {
...@@ -1441,6 +2116,23 @@ LPFC_VPORT_ATTR_R(scan_down, 1, 0, 1, ...@@ -1441,6 +2116,23 @@ LPFC_VPORT_ATTR_R(scan_down, 1, 0, 1,
# Set loop mode if you want to run as an NL_Port. Value range is [0,0x6]. # Set loop mode if you want to run as an NL_Port. Value range is [0,0x6].
# Default value is 0. # Default value is 0.
*/ */
/**
* lpfc_topology_set: Set the adapters topology field.
* @phba: lpfc_hba pointer.
* @val: topology value.
*
* Description:
* If val is in a valid range then set the adapter's topology field and
* issue a lip; if the lip fails reset the topology to the old value.
*
* If the value is not in range log a kernel error message and return an error.
*
* Returns:
* zero if val is in range and lip okay
* non-zero return value from lpfc_issue_lip()
* -EINVAL val out of range
**/
static int static int
lpfc_topology_set(struct lpfc_hba *phba, int val) lpfc_topology_set(struct lpfc_hba *phba, int val)
{ {
...@@ -1479,6 +2171,24 @@ static DEVICE_ATTR(lpfc_topology, S_IRUGO | S_IWUSR, ...@@ -1479,6 +2171,24 @@ static DEVICE_ATTR(lpfc_topology, S_IRUGO | S_IWUSR,
# 8 = 8 Gigabaud # 8 = 8 Gigabaud
# Value range is [0,8]. Default value is 0. # Value range is [0,8]. Default value is 0.
*/ */
/**
* lpfc_link_speed_set: Set the adapters link speed.
* @phba: lpfc_hba pointer.
* @val: link speed value.
*
* Description:
* If val is in a valid range then set the adapter's link speed field and
* issue a lip; if the lip fails reset the link speed to the old value.
*
* Notes:
* If the value is not in range log a kernel error message and return an error.
*
* Returns:
* zero if val is in range and lip okay.
* non-zero return value from lpfc_issue_lip()
* -EINVAL val out of range
**/
static int static int
lpfc_link_speed_set(struct lpfc_hba *phba, int val) lpfc_link_speed_set(struct lpfc_hba *phba, int val)
{ {
...@@ -1513,6 +2223,23 @@ static int lpfc_link_speed = 0; ...@@ -1513,6 +2223,23 @@ static int lpfc_link_speed = 0;
module_param(lpfc_link_speed, int, 0); module_param(lpfc_link_speed, int, 0);
MODULE_PARM_DESC(lpfc_link_speed, "Select link speed"); MODULE_PARM_DESC(lpfc_link_speed, "Select link speed");
lpfc_param_show(link_speed) lpfc_param_show(link_speed)
/**
* lpfc_link_speed_init: Set the adapters link speed.
* @phba: lpfc_hba pointer.
* @val: link speed value.
*
* Description:
* If val is in a valid range then set the adapter's link speed field.
*
* Notes:
* If the value is not in range log a kernel error message, clear the link
* speed and return an error.
*
* Returns:
* zero if val saved.
* -EINVAL val out of range
**/
static int static int
lpfc_link_speed_init(struct lpfc_hba *phba, int val) lpfc_link_speed_init(struct lpfc_hba *phba, int val)
{ {
...@@ -1734,6 +2461,24 @@ struct device_attribute *lpfc_vport_attrs[] = { ...@@ -1734,6 +2461,24 @@ struct device_attribute *lpfc_vport_attrs[] = {
NULL, NULL,
}; };
/**
* sysfs_ctlreg_write: Write method for writing to ctlreg.
* @kobj: kernel kobject that contains the kernel class device.
* @bin_attr: kernel attributes passed to us.
* @buf: contains the data to be written to the adapter IOREG space.
* @off: offset into buffer to beginning of data.
* @count: bytes to transfer.
*
* Description:
* Accessed via /sys/class/scsi_host/hostxxx/ctlreg.
* Uses the adapter io control registers to send buf contents to the adapter.
*
* Returns:
* -ERANGE off and count combo out of range
* -EINVAL off, count or buff address invalid
* -EPERM adapter is offline
* value of count, buf contents written
**/
static ssize_t static ssize_t
sysfs_ctlreg_write(struct kobject *kobj, struct bin_attribute *bin_attr, sysfs_ctlreg_write(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count) char *buf, loff_t off, size_t count)
...@@ -1766,6 +2511,23 @@ sysfs_ctlreg_write(struct kobject *kobj, struct bin_attribute *bin_attr, ...@@ -1766,6 +2511,23 @@ sysfs_ctlreg_write(struct kobject *kobj, struct bin_attribute *bin_attr,
return count; return count;
} }
/**
* sysfs_ctlreg_read: Read method for reading from ctlreg.
* @kobj: kernel kobject that contains the kernel class device.
* @bin_attr: kernel attributes passed to us.
* @buf: if succesful contains the data from the adapter IOREG space.
* @off: offset into buffer to beginning of data.
* @count: bytes to transfer.
*
* Description:
* Accessed via /sys/class/scsi_host/hostxxx/ctlreg.
* Uses the adapter io control registers to read data into buf.
*
* Returns:
* -ERANGE off and count combo out of range
* -EINVAL off, count or buff address invalid
* value of count, buf contents read
**/
static ssize_t static ssize_t
sysfs_ctlreg_read(struct kobject *kobj, struct bin_attribute *bin_attr, sysfs_ctlreg_read(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count) char *buf, loff_t off, size_t count)
...@@ -1810,7 +2572,10 @@ static struct bin_attribute sysfs_ctlreg_attr = { ...@@ -1810,7 +2572,10 @@ static struct bin_attribute sysfs_ctlreg_attr = {
.write = sysfs_ctlreg_write, .write = sysfs_ctlreg_write,
}; };
/**
* sysfs_mbox_idle: frees the sysfs mailbox.
* @phba: lpfc_hba pointer
**/
static void static void
sysfs_mbox_idle(struct lpfc_hba *phba) sysfs_mbox_idle(struct lpfc_hba *phba)
{ {
...@@ -1824,6 +2589,27 @@ sysfs_mbox_idle(struct lpfc_hba *phba) ...@@ -1824,6 +2589,27 @@ sysfs_mbox_idle(struct lpfc_hba *phba)
} }
} }
/**
* sysfs_mbox_write: Write method for writing information via mbox.
* @kobj: kernel kobject that contains the kernel class device.
* @bin_attr: kernel attributes passed to us.
* @buf: contains the data to be written to sysfs mbox.
* @off: offset into buffer to beginning of data.
* @count: bytes to transfer.
*
* Description:
* Accessed via /sys/class/scsi_host/hostxxx/mbox.
* Uses the sysfs mbox to send buf contents to the adapter.
*
* Returns:
* -ERANGE off and count combo out of range
* -EINVAL off, count or buff address invalid
* zero if count is zero
* -EPERM adapter is offline
* -ENOMEM failed to allocate memory for the mail box
* -EAGAIN offset, state or mbox is NULL
* count number of bytes transferred
**/
static ssize_t static ssize_t
sysfs_mbox_write(struct kobject *kobj, struct bin_attribute *bin_attr, sysfs_mbox_write(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count) char *buf, loff_t off, size_t count)
...@@ -1878,6 +2664,29 @@ sysfs_mbox_write(struct kobject *kobj, struct bin_attribute *bin_attr, ...@@ -1878,6 +2664,29 @@ sysfs_mbox_write(struct kobject *kobj, struct bin_attribute *bin_attr,
return count; return count;
} }
/**
* sysfs_mbox_read: Read method for reading information via mbox.
* @kobj: kernel kobject that contains the kernel class device.
* @bin_attr: kernel attributes passed to us.
* @buf: contains the data to be read from sysfs mbox.
* @off: offset into buffer to beginning of data.
* @count: bytes to transfer.
*
* Description:
* Accessed via /sys/class/scsi_host/hostxxx/mbox.
* Uses the sysfs mbox to receive data from to the adapter.
*
* Returns:
* -ERANGE off greater than mailbox command size
* -EINVAL off, count or buff address invalid
* zero if off and count are zero
* -EACCES adapter over temp
* -EPERM garbage can value to catch a multitude of errors
* -EAGAIN management IO not permitted, state or off error
* -ETIME mailbox timeout
* -ENODEV mailbox error
* count number of bytes transferred
**/
static ssize_t static ssize_t
sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr, sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count) char *buf, loff_t off, size_t count)
...@@ -2059,6 +2868,14 @@ static struct bin_attribute sysfs_mbox_attr = { ...@@ -2059,6 +2868,14 @@ static struct bin_attribute sysfs_mbox_attr = {
.write = sysfs_mbox_write, .write = sysfs_mbox_write,
}; };
/**
* lpfc_alloc_sysfs_attr: Creates the sysfs, ctlreg, menlo and mbox entries.
* @vport: address of lpfc vport structure.
*
* Return codes:
* zero on success
* error return code from sysfs_create_bin_file()
**/
int int
lpfc_alloc_sysfs_attr(struct lpfc_vport *vport) lpfc_alloc_sysfs_attr(struct lpfc_vport *vport)
{ {
...@@ -2082,6 +2899,10 @@ out: ...@@ -2082,6 +2899,10 @@ out:
return error; return error;
} }
/**
* lpfc_free_sysfs_attr: Removes the sysfs, ctlreg, menlo and mbox entries.
* @vport: address of lpfc vport structure.
**/
void void
lpfc_free_sysfs_attr(struct lpfc_vport *vport) lpfc_free_sysfs_attr(struct lpfc_vport *vport)
{ {
...@@ -2096,6 +2917,10 @@ lpfc_free_sysfs_attr(struct lpfc_vport *vport) ...@@ -2096,6 +2917,10 @@ lpfc_free_sysfs_attr(struct lpfc_vport *vport)
* Dynamic FC Host Attributes Support * Dynamic FC Host Attributes Support
*/ */
/**
* lpfc_get_host_port_id: Copy the vport DID into the scsi host port id.
* @shost: kernel scsi host pointer.
**/
static void static void
lpfc_get_host_port_id(struct Scsi_Host *shost) lpfc_get_host_port_id(struct Scsi_Host *shost)
{ {
...@@ -2105,6 +2930,10 @@ lpfc_get_host_port_id(struct Scsi_Host *shost) ...@@ -2105,6 +2930,10 @@ lpfc_get_host_port_id(struct Scsi_Host *shost)
fc_host_port_id(shost) = vport->fc_myDID; fc_host_port_id(shost) = vport->fc_myDID;
} }
/**
* lpfc_get_host_port_type: Set the value of the scsi host port type.
* @shost: kernel scsi host pointer.
**/
static void static void
lpfc_get_host_port_type(struct Scsi_Host *shost) lpfc_get_host_port_type(struct Scsi_Host *shost)
{ {
...@@ -2133,6 +2962,10 @@ lpfc_get_host_port_type(struct Scsi_Host *shost) ...@@ -2133,6 +2962,10 @@ lpfc_get_host_port_type(struct Scsi_Host *shost)
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
} }
/**
* lpfc_get_host_port_state: Set the value of the scsi host port state.
* @shost: kernel scsi host pointer.
**/
static void static void
lpfc_get_host_port_state(struct Scsi_Host *shost) lpfc_get_host_port_state(struct Scsi_Host *shost)
{ {
...@@ -2167,6 +3000,10 @@ lpfc_get_host_port_state(struct Scsi_Host *shost) ...@@ -2167,6 +3000,10 @@ lpfc_get_host_port_state(struct Scsi_Host *shost)
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
} }
/**
* lpfc_get_host_speed: Set the value of the scsi host speed.
* @shost: kernel scsi host pointer.
**/
static void static void
lpfc_get_host_speed(struct Scsi_Host *shost) lpfc_get_host_speed(struct Scsi_Host *shost)
{ {
...@@ -2199,6 +3036,10 @@ lpfc_get_host_speed(struct Scsi_Host *shost) ...@@ -2199,6 +3036,10 @@ lpfc_get_host_speed(struct Scsi_Host *shost)
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
} }
/**
* lpfc_get_host_fabric_name: Set the value of the scsi host fabric name.
* @shost: kernel scsi host pointer.
**/
static void static void
lpfc_get_host_fabric_name (struct Scsi_Host *shost) lpfc_get_host_fabric_name (struct Scsi_Host *shost)
{ {
...@@ -2221,6 +3062,18 @@ lpfc_get_host_fabric_name (struct Scsi_Host *shost) ...@@ -2221,6 +3062,18 @@ lpfc_get_host_fabric_name (struct Scsi_Host *shost)
fc_host_fabric_name(shost) = node_name; fc_host_fabric_name(shost) = node_name;
} }
/**
* lpfc_get_stats: Return statistical information about the adapter.
* @shost: kernel scsi host pointer.
*
* Notes:
* NULL on error for link down, no mbox pool, sli2 active,
* management not allowed, memory allocation error, or mbox error.
*
* Returns:
* NULL for error
* address of the adapter host statistics
**/
static struct fc_host_statistics * static struct fc_host_statistics *
lpfc_get_stats(struct Scsi_Host *shost) lpfc_get_stats(struct Scsi_Host *shost)
{ {
...@@ -2334,6 +3187,10 @@ lpfc_get_stats(struct Scsi_Host *shost) ...@@ -2334,6 +3187,10 @@ lpfc_get_stats(struct Scsi_Host *shost)
return hs; return hs;
} }
/**
* lpfc_reset_stats: Copy the adapter link stats information.
* @shost: kernel scsi host pointer.
**/
static void static void
lpfc_reset_stats(struct Scsi_Host *shost) lpfc_reset_stats(struct Scsi_Host *shost)
{ {
...@@ -2411,6 +3268,14 @@ lpfc_reset_stats(struct Scsi_Host *shost) ...@@ -2411,6 +3268,14 @@ lpfc_reset_stats(struct Scsi_Host *shost)
* are no sysfs handlers for link_down_tmo. * are no sysfs handlers for link_down_tmo.
*/ */
/**
* lpfc_get_node_by_target: Return the nodelist for a target.
* @starget: kernel scsi target pointer.
*
* Returns:
* address of the node list if found
* NULL target not found
**/
static struct lpfc_nodelist * static struct lpfc_nodelist *
lpfc_get_node_by_target(struct scsi_target *starget) lpfc_get_node_by_target(struct scsi_target *starget)
{ {
...@@ -2432,6 +3297,10 @@ lpfc_get_node_by_target(struct scsi_target *starget) ...@@ -2432,6 +3297,10 @@ lpfc_get_node_by_target(struct scsi_target *starget)
return NULL; return NULL;
} }
/**
* lpfc_get_starget_port_id: Set the target port id to the ndlp DID or -1.
* @starget: kernel scsi target pointer.
**/
static void static void
lpfc_get_starget_port_id(struct scsi_target *starget) lpfc_get_starget_port_id(struct scsi_target *starget)
{ {
...@@ -2440,6 +3309,12 @@ lpfc_get_starget_port_id(struct scsi_target *starget) ...@@ -2440,6 +3309,12 @@ lpfc_get_starget_port_id(struct scsi_target *starget)
fc_starget_port_id(starget) = ndlp ? ndlp->nlp_DID : -1; fc_starget_port_id(starget) = ndlp ? ndlp->nlp_DID : -1;
} }
/**
* lpfc_get_starget_node_name: Set the target node name.
* @starget: kernel scsi target pointer.
*
* Description: Set the target node name to the ndlp node name wwn or zero.
**/
static void static void
lpfc_get_starget_node_name(struct scsi_target *starget) lpfc_get_starget_node_name(struct scsi_target *starget)
{ {
...@@ -2449,6 +3324,12 @@ lpfc_get_starget_node_name(struct scsi_target *starget) ...@@ -2449,6 +3324,12 @@ lpfc_get_starget_node_name(struct scsi_target *starget)
ndlp ? wwn_to_u64(ndlp->nlp_nodename.u.wwn) : 0; ndlp ? wwn_to_u64(ndlp->nlp_nodename.u.wwn) : 0;
} }
/**
* lpfc_get_starget_port_name: Set the target port name.
* @starget: kernel scsi target pointer.
*
* Description: set the target port name to the ndlp port name wwn or zero.
**/
static void static void
lpfc_get_starget_port_name(struct scsi_target *starget) lpfc_get_starget_port_name(struct scsi_target *starget)
{ {
...@@ -2458,6 +3339,15 @@ lpfc_get_starget_port_name(struct scsi_target *starget) ...@@ -2458,6 +3339,15 @@ lpfc_get_starget_port_name(struct scsi_target *starget)
ndlp ? wwn_to_u64(ndlp->nlp_portname.u.wwn) : 0; ndlp ? wwn_to_u64(ndlp->nlp_portname.u.wwn) : 0;
} }
/**
* lpfc_set_rport_loss_tmo: Set the rport dev loss tmo.
* @rport: fc rport address.
* @timeout: new value for dev loss tmo.
*
* Description:
* If timeout is non zero set the dev_loss_tmo to timeout, else set
* dev_loss_tmo to one.
**/
static void static void
lpfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) lpfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
{ {
...@@ -2467,7 +3357,18 @@ lpfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) ...@@ -2467,7 +3357,18 @@ lpfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
rport->dev_loss_tmo = 1; rport->dev_loss_tmo = 1;
} }
/**
* lpfc_rport_show_function: Return rport target information.
*
* Description:
* Macro that uses field to generate a function with the name lpfc_show_rport_
*
* lpfc_show_rport_##field: returns the bytes formatted in buf
* @cdev: class converted to an fc_rport.
* @buf: on return contains the target_field or zero.
*
* Returns: size of formatted string.
**/
#define lpfc_rport_show_function(field, format_string, sz, cast) \ #define lpfc_rport_show_function(field, format_string, sz, cast) \
static ssize_t \ static ssize_t \
lpfc_show_rport_##field (struct device *dev, \ lpfc_show_rport_##field (struct device *dev, \
...@@ -2602,6 +3503,10 @@ struct fc_function_template lpfc_vport_transport_functions = { ...@@ -2602,6 +3503,10 @@ struct fc_function_template lpfc_vport_transport_functions = {
.vport_disable = lpfc_vport_disable, .vport_disable = lpfc_vport_disable,
}; };
/**
* lpfc_get_cfgparam: Used during probe_one to init the adapter structure.
* @phba: lpfc_hba pointer.
**/
void void
lpfc_get_cfgparam(struct lpfc_hba *phba) lpfc_get_cfgparam(struct lpfc_hba *phba)
{ {
...@@ -2637,6 +3542,10 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) ...@@ -2637,6 +3542,10 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
return; return;
} }
/**
* lpfc_get_vport_cfgparam: Used during port create, init the vport structure.
* @vport: lpfc_vport pointer.
**/
void void
lpfc_get_vport_cfgparam(struct lpfc_vport *vport) lpfc_get_vport_cfgparam(struct lpfc_vport *vport)
{ {
......
/******************************************************************* /*******************************************************************
* This file is part of the Emulex Linux Device Driver for * * This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. * * Fibre Channel Host Bus Adapters. *
* Copyright (C) 2007 Emulex. All rights reserved. * * Copyright (C) 2007-2008 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. * * EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com * * www.emulex.com *
* * * *
...@@ -46,13 +46,14 @@ ...@@ -46,13 +46,14 @@
#include "lpfc_debugfs.h" #include "lpfc_debugfs.h"
#ifdef CONFIG_LPFC_DEBUG_FS #ifdef CONFIG_LPFC_DEBUG_FS
/* debugfs interface /**
* debugfs interface
* *
* To access this interface the user should: * To access this interface the user should:
* # mkdir /debug * # mkdir /debug
* # mount -t debugfs none /debug * # mount -t debugfs none /debug
* *
* The lpfc debugfs directory hierachy is: * The lpfc debugfs directory hierarchy is:
* lpfc/lpfcX/vportY * lpfc/lpfcX/vportY
* where X is the lpfc hba unique_id * where X is the lpfc hba unique_id
* where Y is the vport VPI on that hba * where Y is the vport VPI on that hba
...@@ -61,14 +62,21 @@ ...@@ -61,14 +62,21 @@
* discovery_trace * discovery_trace
* This is an ACSII readable file that contains a trace of the last * This is an ACSII readable file that contains a trace of the last
* lpfc_debugfs_max_disc_trc events that happened on a specific vport. * lpfc_debugfs_max_disc_trc events that happened on a specific vport.
* See lpfc_debugfs.h for different categories of * See lpfc_debugfs.h for different categories of discovery events.
* discovery events. To enable the discovery trace, the following * To enable the discovery trace, the following module parameters must be set:
* module parameters must be set:
* lpfc_debugfs_enable=1 Turns on lpfc debugfs filesystem support * lpfc_debugfs_enable=1 Turns on lpfc debugfs filesystem support
* lpfc_debugfs_max_disc_trc=X Where X is the event trace depth for * lpfc_debugfs_max_disc_trc=X Where X is the event trace depth for
* EACH vport. X MUST also be a power of 2. * EACH vport. X MUST also be a power of 2.
* lpfc_debugfs_mask_disc_trc=Y Where Y is an event mask as defined in * lpfc_debugfs_mask_disc_trc=Y Where Y is an event mask as defined in
* lpfc_debugfs.h . * lpfc_debugfs.h .
*
* slow_ring_trace
* This is an ACSII readable file that contains a trace of the last
* lpfc_debugfs_max_slow_ring_trc events that happened on a specific HBA.
* To enable the slow ring trace, the following module parameters must be set:
* lpfc_debugfs_enable=1 Turns on lpfc debugfs filesystem support
* lpfc_debugfs_max_slow_ring_trc=X Where X is the event trace depth for
* the HBA. X MUST also be a power of 2.
*/ */
static int lpfc_debugfs_enable = 1; static int lpfc_debugfs_enable = 1;
module_param(lpfc_debugfs_enable, int, 0); module_param(lpfc_debugfs_enable, int, 0);
...@@ -117,6 +125,25 @@ struct lpfc_debug { ...@@ -117,6 +125,25 @@ struct lpfc_debug {
static atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0); static atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0);
static unsigned long lpfc_debugfs_start_time = 0L; static unsigned long lpfc_debugfs_start_time = 0L;
/**
* lpfc_debugfs_disc_trc_data - Dump discovery logging to a buffer.
* @vport: The vport to gather the log info from.
* @buf: The buffer to dump log into.
* @size: The maximum amount of data to process.
*
* Description:
* This routine gathers the lpfc discovery debugfs data from the @vport and
* dumps it to @buf up to @size number of bytes. It will start at the next entry
* in the log and process the log until the end of the buffer. Then it will
* gather from the beginning of the log and process until the current entry.
*
* Notes:
* Discovery logging will be disabled while while this routine dumps the log.
*
* Return Value:
* This routine returns the amount of bytes that were dumped into @buf and will
* not exceed @size.
**/
static int static int
lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size) lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size)
{ {
...@@ -125,7 +152,6 @@ lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size) ...@@ -125,7 +152,6 @@ lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size)
struct lpfc_debugfs_trc *dtp; struct lpfc_debugfs_trc *dtp;
char buffer[LPFC_DEBUG_TRC_ENTRY_SIZE]; char buffer[LPFC_DEBUG_TRC_ENTRY_SIZE];
enable = lpfc_debugfs_enable; enable = lpfc_debugfs_enable;
lpfc_debugfs_enable = 0; lpfc_debugfs_enable = 0;
...@@ -159,6 +185,25 @@ lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size) ...@@ -159,6 +185,25 @@ lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size)
return len; return len;
} }
/**
* lpfc_debugfs_slow_ring_trc_data - Dump slow ring logging to a buffer.
* @phba: The HBA to gather the log info from.
* @buf: The buffer to dump log into.
* @size: The maximum amount of data to process.
*
* Description:
* This routine gathers the lpfc slow ring debugfs data from the @phba and
* dumps it to @buf up to @size number of bytes. It will start at the next entry
* in the log and process the log until the end of the buffer. Then it will
* gather from the beginning of the log and process until the current entry.
*
* Notes:
* Slow ring logging will be disabled while while this routine dumps the log.
*
* Return Value:
* This routine returns the amount of bytes that were dumped into @buf and will
* not exceed @size.
**/
static int static int
lpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size) lpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size)
{ {
...@@ -203,6 +248,25 @@ lpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size) ...@@ -203,6 +248,25 @@ lpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size)
static int lpfc_debugfs_last_hbq = -1; static int lpfc_debugfs_last_hbq = -1;
/**
* lpfc_debugfs_hbqinfo_data - Dump host buffer queue info to a buffer.
* @phba: The HBA to gather host buffer info from.
* @buf: The buffer to dump log into.
* @size: The maximum amount of data to process.
*
* Description:
* This routine dumps the host buffer queue info from the @phba to @buf up to
* @size number of bytes. A header that describes the current hbq state will be
* dumped to @buf first and then info on each hbq entry will be dumped to @buf
* until @size bytes have been dumped or all the hbq info has been dumped.
*
* Notes:
* This routine will rotate through each configured HBQ each time called.
*
* Return Value:
* This routine returns the amount of bytes that were dumped into @buf and will
* not exceed @size.
**/
static int static int
lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size) lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size)
{ {
...@@ -303,6 +367,24 @@ skipit: ...@@ -303,6 +367,24 @@ skipit:
static int lpfc_debugfs_last_hba_slim_off; static int lpfc_debugfs_last_hba_slim_off;
/**
* lpfc_debugfs_dumpHBASlim_data - Dump HBA SLIM info to a buffer.
* @phba: The HBA to gather SLIM info from.
* @buf: The buffer to dump log into.
* @size: The maximum amount of data to process.
*
* Description:
* This routine dumps the current contents of HBA SLIM for the HBA associated
* with @phba to @buf up to @size bytes of data. This is the raw HBA SLIM data.
*
* Notes:
* This routine will only dump up to 1024 bytes of data each time called and
* should be called multiple times to dump the entire HBA SLIM.
*
* Return Value:
* This routine returns the amount of bytes that were dumped into @buf and will
* not exceed @size.
**/
static int static int
lpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size) lpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size)
{ {
...@@ -342,6 +424,21 @@ lpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size) ...@@ -342,6 +424,21 @@ lpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size)
return len; return len;
} }
/**
* lpfc_debugfs_dumpHostSlim_data - Dump host SLIM info to a buffer.
* @phba: The HBA to gather Host SLIM info from.
* @buf: The buffer to dump log into.
* @size: The maximum amount of data to process.
*
* Description:
* This routine dumps the current contents of host SLIM for the host associated
* with @phba to @buf up to @size bytes of data. The dump will contain the
* Mailbox, PCB, Rings, and Registers that are located in host memory.
*
* Return Value:
* This routine returns the amount of bytes that were dumped into @buf and will
* not exceed @size.
**/
static int static int
lpfc_debugfs_dumpHostSlim_data(struct lpfc_hba *phba, char *buf, int size) lpfc_debugfs_dumpHostSlim_data(struct lpfc_hba *phba, char *buf, int size)
{ {
...@@ -430,6 +527,21 @@ lpfc_debugfs_dumpHostSlim_data(struct lpfc_hba *phba, char *buf, int size) ...@@ -430,6 +527,21 @@ lpfc_debugfs_dumpHostSlim_data(struct lpfc_hba *phba, char *buf, int size)
return len; return len;
} }
/**
* lpfc_debugfs_nodelist_data - Dump target node list to a buffer.
* @vport: The vport to gather target node info from.
* @buf: The buffer to dump log into.
* @size: The maximum amount of data to process.
*
* Description:
* This routine dumps the current target node list associated with @vport to
* @buf up to @size bytes of data. Each node entry in the dump will contain a
* node state, DID, WWPN, WWNN, RPI, flags, type, and other useful fields.
*
* Return Value:
* This routine returns the amount of bytes that were dumped into @buf and will
* not exceed @size.
**/
static int static int
lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size) lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
{ {
...@@ -513,7 +625,22 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size) ...@@ -513,7 +625,22 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
} }
#endif #endif
/**
* lpfc_debugfs_disc_trc - Store discovery trace log.
* @vport: The vport to associate this trace string with for retrieval.
* @mask: Log entry classification.
* @fmt: Format string to be displayed when dumping the log.
* @data1: 1st data parameter to be applied to @fmt.
* @data2: 2nd data parameter to be applied to @fmt.
* @data3: 3rd data parameter to be applied to @fmt.
*
* Description:
* This routine is used by the driver code to add a debugfs log entry to the
* discovery trace buffer associated with @vport. Only entries with a @mask that
* match the current debugfs discovery mask will be saved. Entries that do not
* match will be thrown away. @fmt, @data1, @data2, and @data3 are used like
* printf when displaying the log.
**/
inline void inline void
lpfc_debugfs_disc_trc(struct lpfc_vport *vport, int mask, char *fmt, lpfc_debugfs_disc_trc(struct lpfc_vport *vport, int mask, char *fmt,
uint32_t data1, uint32_t data2, uint32_t data3) uint32_t data1, uint32_t data2, uint32_t data3)
...@@ -542,6 +669,19 @@ lpfc_debugfs_disc_trc(struct lpfc_vport *vport, int mask, char *fmt, ...@@ -542,6 +669,19 @@ lpfc_debugfs_disc_trc(struct lpfc_vport *vport, int mask, char *fmt,
return; return;
} }
/**
* lpfc_debugfs_slow_ring_trc - Store slow ring trace log.
* @phba: The phba to associate this trace string with for retrieval.
* @fmt: Format string to be displayed when dumping the log.
* @data1: 1st data parameter to be applied to @fmt.
* @data2: 2nd data parameter to be applied to @fmt.
* @data3: 3rd data parameter to be applied to @fmt.
*
* Description:
* This routine is used by the driver code to add a debugfs log entry to the
* discovery trace buffer associated with @vport. @fmt, @data1, @data2, and
* @data3 are used like printf when displaying the log.
**/
inline void inline void
lpfc_debugfs_slow_ring_trc(struct lpfc_hba *phba, char *fmt, lpfc_debugfs_slow_ring_trc(struct lpfc_hba *phba, char *fmt,
uint32_t data1, uint32_t data2, uint32_t data3) uint32_t data1, uint32_t data2, uint32_t data3)
...@@ -568,6 +708,21 @@ lpfc_debugfs_slow_ring_trc(struct lpfc_hba *phba, char *fmt, ...@@ -568,6 +708,21 @@ lpfc_debugfs_slow_ring_trc(struct lpfc_hba *phba, char *fmt,
} }
#ifdef CONFIG_LPFC_DEBUG_FS #ifdef CONFIG_LPFC_DEBUG_FS
/**
* lpfc_debugfs_disc_trc_open - Open the discovery trace log.
* @inode: The inode pointer that contains a vport pointer.
* @file: The file pointer to attach the log output.
*
* Description:
* This routine is the entry point for the debugfs open file operation. It gets
* the vport from the i_private field in @inode, allocates the necessary buffer
* for the log, fills the buffer from the in-memory log for this vport, and then
* returns a pointer to that log in the private_data field in @file.
*
* Returns:
* This function returns zero if successful. On error it will return an negative
* error value.
**/
static int static int
lpfc_debugfs_disc_trc_open(struct inode *inode, struct file *file) lpfc_debugfs_disc_trc_open(struct inode *inode, struct file *file)
{ {
...@@ -585,7 +740,7 @@ lpfc_debugfs_disc_trc_open(struct inode *inode, struct file *file) ...@@ -585,7 +740,7 @@ lpfc_debugfs_disc_trc_open(struct inode *inode, struct file *file)
if (!debug) if (!debug)
goto out; goto out;
/* Round to page boundry */ /* Round to page boundary */
size = (lpfc_debugfs_max_disc_trc * LPFC_DEBUG_TRC_ENTRY_SIZE); size = (lpfc_debugfs_max_disc_trc * LPFC_DEBUG_TRC_ENTRY_SIZE);
size = PAGE_ALIGN(size); size = PAGE_ALIGN(size);
...@@ -603,6 +758,21 @@ out: ...@@ -603,6 +758,21 @@ out:
return rc; return rc;
} }
/**
* lpfc_debugfs_slow_ring_trc_open - Open the Slow Ring trace log.
* @inode: The inode pointer that contains a vport pointer.
* @file: The file pointer to attach the log output.
*
* Description:
* This routine is the entry point for the debugfs open file operation. It gets
* the vport from the i_private field in @inode, allocates the necessary buffer
* for the log, fills the buffer from the in-memory log for this vport, and then
* returns a pointer to that log in the private_data field in @file.
*
* Returns:
* This function returns zero if successful. On error it will return an negative
* error value.
**/
static int static int
lpfc_debugfs_slow_ring_trc_open(struct inode *inode, struct file *file) lpfc_debugfs_slow_ring_trc_open(struct inode *inode, struct file *file)
{ {
...@@ -620,7 +790,7 @@ lpfc_debugfs_slow_ring_trc_open(struct inode *inode, struct file *file) ...@@ -620,7 +790,7 @@ lpfc_debugfs_slow_ring_trc_open(struct inode *inode, struct file *file)
if (!debug) if (!debug)
goto out; goto out;
/* Round to page boundry */ /* Round to page boundary */
size = (lpfc_debugfs_max_slow_ring_trc * LPFC_DEBUG_TRC_ENTRY_SIZE); size = (lpfc_debugfs_max_slow_ring_trc * LPFC_DEBUG_TRC_ENTRY_SIZE);
size = PAGE_ALIGN(size); size = PAGE_ALIGN(size);
...@@ -638,6 +808,21 @@ out: ...@@ -638,6 +808,21 @@ out:
return rc; return rc;
} }
/**
* lpfc_debugfs_hbqinfo_open - Open the hbqinfo debugfs buffer.
* @inode: The inode pointer that contains a vport pointer.
* @file: The file pointer to attach the log output.
*
* Description:
* This routine is the entry point for the debugfs open file operation. It gets
* the vport from the i_private field in @inode, allocates the necessary buffer
* for the log, fills the buffer from the in-memory log for this vport, and then
* returns a pointer to that log in the private_data field in @file.
*
* Returns:
* This function returns zero if successful. On error it will return an negative
* error value.
**/
static int static int
lpfc_debugfs_hbqinfo_open(struct inode *inode, struct file *file) lpfc_debugfs_hbqinfo_open(struct inode *inode, struct file *file)
{ {
...@@ -649,7 +834,7 @@ lpfc_debugfs_hbqinfo_open(struct inode *inode, struct file *file) ...@@ -649,7 +834,7 @@ lpfc_debugfs_hbqinfo_open(struct inode *inode, struct file *file)
if (!debug) if (!debug)
goto out; goto out;
/* Round to page boundry */ /* Round to page boundary */
debug->buffer = kmalloc(LPFC_HBQINFO_SIZE, GFP_KERNEL); debug->buffer = kmalloc(LPFC_HBQINFO_SIZE, GFP_KERNEL);
if (!debug->buffer) { if (!debug->buffer) {
kfree(debug); kfree(debug);
...@@ -665,6 +850,21 @@ out: ...@@ -665,6 +850,21 @@ out:
return rc; return rc;
} }
/**
* lpfc_debugfs_dumpHBASlim_open - Open the Dump HBA SLIM debugfs buffer.
* @inode: The inode pointer that contains a vport pointer.
* @file: The file pointer to attach the log output.
*
* Description:
* This routine is the entry point for the debugfs open file operation. It gets
* the vport from the i_private field in @inode, allocates the necessary buffer
* for the log, fills the buffer from the in-memory log for this vport, and then
* returns a pointer to that log in the private_data field in @file.
*
* Returns:
* This function returns zero if successful. On error it will return an negative
* error value.
**/
static int static int
lpfc_debugfs_dumpHBASlim_open(struct inode *inode, struct file *file) lpfc_debugfs_dumpHBASlim_open(struct inode *inode, struct file *file)
{ {
...@@ -676,7 +876,7 @@ lpfc_debugfs_dumpHBASlim_open(struct inode *inode, struct file *file) ...@@ -676,7 +876,7 @@ lpfc_debugfs_dumpHBASlim_open(struct inode *inode, struct file *file)
if (!debug) if (!debug)
goto out; goto out;
/* Round to page boundry */ /* Round to page boundary */
debug->buffer = kmalloc(LPFC_DUMPHBASLIM_SIZE, GFP_KERNEL); debug->buffer = kmalloc(LPFC_DUMPHBASLIM_SIZE, GFP_KERNEL);
if (!debug->buffer) { if (!debug->buffer) {
kfree(debug); kfree(debug);
...@@ -692,6 +892,21 @@ out: ...@@ -692,6 +892,21 @@ out:
return rc; return rc;
} }
/**
* lpfc_debugfs_dumpHostSlim_open - Open the Dump Host SLIM debugfs buffer.
* @inode: The inode pointer that contains a vport pointer.
* @file: The file pointer to attach the log output.
*
* Description:
* This routine is the entry point for the debugfs open file operation. It gets
* the vport from the i_private field in @inode, allocates the necessary buffer
* for the log, fills the buffer from the in-memory log for this vport, and then
* returns a pointer to that log in the private_data field in @file.
*
* Returns:
* This function returns zero if successful. On error it will return an negative
* error value.
**/
static int static int
lpfc_debugfs_dumpHostSlim_open(struct inode *inode, struct file *file) lpfc_debugfs_dumpHostSlim_open(struct inode *inode, struct file *file)
{ {
...@@ -703,7 +918,7 @@ lpfc_debugfs_dumpHostSlim_open(struct inode *inode, struct file *file) ...@@ -703,7 +918,7 @@ lpfc_debugfs_dumpHostSlim_open(struct inode *inode, struct file *file)
if (!debug) if (!debug)
goto out; goto out;
/* Round to page boundry */ /* Round to page boundary */
debug->buffer = kmalloc(LPFC_DUMPHOSTSLIM_SIZE, GFP_KERNEL); debug->buffer = kmalloc(LPFC_DUMPHOSTSLIM_SIZE, GFP_KERNEL);
if (!debug->buffer) { if (!debug->buffer) {
kfree(debug); kfree(debug);
...@@ -719,6 +934,21 @@ out: ...@@ -719,6 +934,21 @@ out:
return rc; return rc;
} }
/**
* lpfc_debugfs_nodelist_open - Open the nodelist debugfs file.
* @inode: The inode pointer that contains a vport pointer.
* @file: The file pointer to attach the log output.
*
* Description:
* This routine is the entry point for the debugfs open file operation. It gets
* the vport from the i_private field in @inode, allocates the necessary buffer
* for the log, fills the buffer from the in-memory log for this vport, and then
* returns a pointer to that log in the private_data field in @file.
*
* Returns:
* This function returns zero if successful. On error it will return an negative
* error value.
**/
static int static int
lpfc_debugfs_nodelist_open(struct inode *inode, struct file *file) lpfc_debugfs_nodelist_open(struct inode *inode, struct file *file)
{ {
...@@ -730,7 +960,7 @@ lpfc_debugfs_nodelist_open(struct inode *inode, struct file *file) ...@@ -730,7 +960,7 @@ lpfc_debugfs_nodelist_open(struct inode *inode, struct file *file)
if (!debug) if (!debug)
goto out; goto out;
/* Round to page boundry */ /* Round to page boundary */
debug->buffer = kmalloc(LPFC_NODELIST_SIZE, GFP_KERNEL); debug->buffer = kmalloc(LPFC_NODELIST_SIZE, GFP_KERNEL);
if (!debug->buffer) { if (!debug->buffer) {
kfree(debug); kfree(debug);
...@@ -746,6 +976,23 @@ out: ...@@ -746,6 +976,23 @@ out:
return rc; return rc;
} }
/**
* lpfc_debugfs_lseek - Seek through a debugfs file.
* @file: The file pointer to seek through.
* @off: The offset to seek to or the amount to seek by.
* @whence: Indicates how to seek.
*
* Description:
* This routine is the entry point for the debugfs lseek file operation. The
* @whence parameter indicates whether @off is the offset to directly seek to,
* or if it is a value to seek forward or reverse by. This function figures out
* what the new offset of the debugfs file will be and assigns that value to the
* f_pos field of @file.
*
* Returns:
* This function returns the new offset if successful and returns a negative
* error if unable to process the seek.
**/
static loff_t static loff_t
lpfc_debugfs_lseek(struct file *file, loff_t off, int whence) lpfc_debugfs_lseek(struct file *file, loff_t off, int whence)
{ {
...@@ -767,6 +1014,22 @@ lpfc_debugfs_lseek(struct file *file, loff_t off, int whence) ...@@ -767,6 +1014,22 @@ lpfc_debugfs_lseek(struct file *file, loff_t off, int whence)
return (pos < 0 || pos > debug->len) ? -EINVAL : (file->f_pos = pos); return (pos < 0 || pos > debug->len) ? -EINVAL : (file->f_pos = pos);
} }
/**
* lpfc_debugfs_read - Read a debugfs file.
* @file: The file pointer to read from.
* @buf: The buffer to copy the data to.
* @nbytes: The number of bytes to read.
* @ppos: The position in the file to start reading from.
*
* Description:
* This routine reads data from from the buffer indicated in the private_data
* field of @file. It will start reading at @ppos and copy up to @nbytes of
* data to @buf.
*
* Returns:
* This function returns the amount of data that was read (this could be less
* than @nbytes if the end of the file was reached) or a negative error value.
**/
static ssize_t static ssize_t
lpfc_debugfs_read(struct file *file, char __user *buf, lpfc_debugfs_read(struct file *file, char __user *buf,
size_t nbytes, loff_t *ppos) size_t nbytes, loff_t *ppos)
...@@ -776,6 +1039,18 @@ lpfc_debugfs_read(struct file *file, char __user *buf, ...@@ -776,6 +1039,18 @@ lpfc_debugfs_read(struct file *file, char __user *buf,
debug->len); debug->len);
} }
/**
* lpfc_debugfs_release - Release the buffer used to store debugfs file data.
* @inode: The inode pointer that contains a vport pointer. (unused)
* @file: The file pointer that contains the buffer to release.
*
* Description:
* This routine frees the buffer that was allocated when the debugfs file was
* opened.
*
* Returns:
* This function returns zero.
**/
static int static int
lpfc_debugfs_release(struct inode *inode, struct file *file) lpfc_debugfs_release(struct inode *inode, struct file *file)
{ {
...@@ -845,6 +1120,16 @@ static struct dentry *lpfc_debugfs_root = NULL; ...@@ -845,6 +1120,16 @@ static struct dentry *lpfc_debugfs_root = NULL;
static atomic_t lpfc_debugfs_hba_count; static atomic_t lpfc_debugfs_hba_count;
#endif #endif
/**
* lpfc_debugfs_initialize - Initialize debugfs for a vport.
* @vport: The vport pointer to initialize.
*
* Description:
* When Debugfs is configured this routine sets up the lpfc debugfs file system.
* If not already created, this routine will create the lpfc directory, and
* lpfcX directory (for this HBA), and vportX directory for this vport. It will
* also create each file used to access lpfc specific debugfs information.
**/
inline void inline void
lpfc_debugfs_initialize(struct lpfc_vport *vport) lpfc_debugfs_initialize(struct lpfc_vport *vport)
{ {
...@@ -1033,7 +1318,17 @@ debug_failed: ...@@ -1033,7 +1318,17 @@ debug_failed:
#endif #endif
} }
/**
* lpfc_debugfs_terminate - Tear down debugfs infrastructure for this vport.
* @vport: The vport pointer to remove from debugfs.
*
* Description:
* When Debugfs is configured this routine removes debugfs file system elements
* that are specific to this vport. It also checks to see if there are any
* users left for the debugfs directories associated with the HBA and driver. If
* this is the last user of the HBA directory or driver directory then it will
* remove those from the debugfs infrastructure as well.
**/
inline void inline void
lpfc_debugfs_terminate(struct lpfc_vport *vport) lpfc_debugfs_terminate(struct lpfc_vport *vport)
{ {
...@@ -1096,5 +1391,3 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport) ...@@ -1096,5 +1391,3 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
#endif #endif
return; return;
} }
...@@ -53,6 +53,28 @@ static void lpfc_register_new_vport(struct lpfc_hba *phba, ...@@ -53,6 +53,28 @@ static void lpfc_register_new_vport(struct lpfc_hba *phba,
static int lpfc_max_els_tries = 3; static int lpfc_max_els_tries = 3;
/**
* lpfc_els_chk_latt: Check host link attention event for a vport.
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine checks whether there is an outstanding host link
* attention event during the discovery process with the @vport. It is done
* by reading the HBA's Host Attention (HA) register. If there is any host
* link attention events during this @vport's discovery process, the @vport
* shall be marked as FC_ABORT_DISCOVERY, a host link attention clear shall
* be issued if the link state is not already in host link cleared state,
* and a return code shall indicate whether the host link attention event
* had happened.
*
* Note that, if either the host link is in state LPFC_LINK_DOWN or @vport
* state in LPFC_VPORT_READY, the request for checking host link attention
* event will be ignored and a return code shall indicate no host link
* attention event had happened.
*
* Return codes
* 0 - no host link attention event happened
* 1 - host link attention event happened
**/
int int
lpfc_els_chk_latt(struct lpfc_vport *vport) lpfc_els_chk_latt(struct lpfc_vport *vport)
{ {
...@@ -92,6 +114,34 @@ lpfc_els_chk_latt(struct lpfc_vport *vport) ...@@ -92,6 +114,34 @@ lpfc_els_chk_latt(struct lpfc_vport *vport)
return 1; return 1;
} }
/**
* lpfc_prep_els_iocb: Allocate and prepare a lpfc iocb data structure.
* @vport: pointer to a host virtual N_Port data structure.
* @expectRsp: flag indicating whether response is expected.
* @cmdSize: size of the ELS command.
* @retry: number of retries to the command IOCB when it fails.
* @ndlp: pointer to a node-list data structure.
* @did: destination identifier.
* @elscmd: the ELS command code.
*
* This routine is used for allocating a lpfc-IOCB data structure from
* the driver lpfc-IOCB free-list and prepare the IOCB with the parameters
* passed into the routine for discovery state machine to issue an Extended
* Link Service (ELS) commands. It is a generic lpfc-IOCB allocation
* and preparation routine that is used by all the discovery state machine
* routines and the ELS command-specific fields will be later set up by
* the individual discovery machine routines after calling this routine
* allocating and preparing a generic IOCB data structure. It fills in the
* Buffer Descriptor Entries (BDEs), allocates buffers for both command
* payload and response payload (if expected). The reference count on the
* ndlp is incremented by 1 and the reference to the ndlp is put into
* context1 of the IOCB data structure for this IOCB to hold the ndlp
* reference for the command's callback function to access later.
*
* Return code
* Pointer to the newly allocated/prepared els iocb data structure
* NULL - when els iocb data structure allocation/preparation failed
**/
static struct lpfc_iocbq * static struct lpfc_iocbq *
lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
uint16_t cmdSize, uint8_t retry, uint16_t cmdSize, uint8_t retry,
...@@ -233,6 +283,22 @@ els_iocb_free_pcmb_exit: ...@@ -233,6 +283,22 @@ els_iocb_free_pcmb_exit:
return NULL; return NULL;
} }
/**
* lpfc_issue_fabric_reglogin: Issue fabric registration login for a vport.
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine issues a fabric registration login for a @vport. An
* active ndlp node with Fabric_DID must already exist for this @vport.
* The routine invokes two mailbox commands to carry out fabric registration
* login through the HBA firmware: the first mailbox command requests the
* HBA to perform link configuration for the @vport; and the second mailbox
* command requests the HBA to perform the actual fabric registration login
* with the @vport.
*
* Return code
* 0 - successfully issued fabric registration login for @vport
* -ENXIO -- failed to issue fabric registration login for @vport
**/
static int static int
lpfc_issue_fabric_reglogin(struct lpfc_vport *vport) lpfc_issue_fabric_reglogin(struct lpfc_vport *vport)
{ {
...@@ -313,6 +379,26 @@ fail: ...@@ -313,6 +379,26 @@ fail:
return -ENXIO; return -ENXIO;
} }
/**
* lpfc_cmpl_els_flogi_fabric: Completion function for flogi to a fabric port.
* @vport: pointer to a host virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
* @sp: pointer to service parameter data structure.
* @irsp: pointer to the IOCB within the lpfc response IOCB.
*
* This routine is invoked by the lpfc_cmpl_els_flogi() completion callback
* function to handle the completion of a Fabric Login (FLOGI) into a fabric
* port in a fabric topology. It properly sets up the parameters to the @ndlp
* from the IOCB response. It also check the newly assigned N_Port ID to the
* @vport against the previously assigned N_Port ID. If it is different from
* the previously assigned Destination ID (DID), the lpfc_unreg_rpi() routine
* is invoked on all the remaining nodes with the @vport to unregister the
* Remote Port Indicators (RPIs). Finally, the lpfc_issue_fabric_reglogin()
* is invoked to register login to the fabric.
*
* Return code
* 0 - Success (currently, always return 0)
**/
static int static int
lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
struct serv_parm *sp, IOCB_t *irsp) struct serv_parm *sp, IOCB_t *irsp)
...@@ -416,9 +502,26 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -416,9 +502,26 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
return 0; return 0;
} }
/* /**
* We FLOGIed into an NPort, initiate pt2pt protocol * lpfc_cmpl_els_flogi_nport: Completion function for flogi to an N_Port.
*/ * @vport: pointer to a host virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
* @sp: pointer to service parameter data structure.
*
* This routine is invoked by the lpfc_cmpl_els_flogi() completion callback
* function to handle the completion of a Fabric Login (FLOGI) into an N_Port
* in a point-to-point topology. First, the @vport's N_Port Name is compared
* with the received N_Port Name: if the @vport's N_Port Name is greater than
* the received N_Port Name lexicographically, this node shall assign local
* N_Port ID (PT2PT_LocalID: 1) and remote N_Port ID (PT2PT_RemoteID: 2) and
* will send out Port Login (PLOGI) with the N_Port IDs assigned. Otherwise,
* this node shall just wait for the remote node to issue PLOGI and assign
* N_Port IDs.
*
* Return code
* 0 - Success
* -ENXIO - Fail
**/
static int static int
lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
struct serv_parm *sp) struct serv_parm *sp)
...@@ -516,6 +619,29 @@ fail: ...@@ -516,6 +619,29 @@ fail:
return -ENXIO; return -ENXIO;
} }
/**
* lpfc_cmpl_els_flogi: Completion callback function for flogi.
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
*
* This routine is the top-level completion callback function for issuing
* a Fabric Login (FLOGI) command. If the response IOCB reported error,
* the lpfc_els_retry() routine shall be invoked to retry the FLOGI. If
* retry has been made (either immediately or delayed with lpfc_els_retry()
* returning 1), the command IOCB will be released and function returned.
* If the retry attempt has been given up (possibly reach the maximum
* number of retries), one additional decrement of ndlp reference shall be
* invoked before going out after releasing the command IOCB. This will
* actually release the remote node (Note, lpfc_els_free_iocb() will also
* invoke one decrement of ndlp reference count). If no error reported in
* the IOCB status, the command Port ID field is used to determine whether
* this is a point-to-point topology or a fabric topology: if the Port ID
* field is assigned, it is a fabric topology; otherwise, it is a
* point-to-point topology. The routine lpfc_cmpl_els_flogi_fabric() or
* lpfc_cmpl_els_flogi_nport() shall be invoked accordingly to handle the
* specific topology completion conditions.
**/
static void static void
lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb) struct lpfc_iocbq *rspiocb)
...@@ -618,6 +744,28 @@ out: ...@@ -618,6 +744,28 @@ out:
lpfc_els_free_iocb(phba, cmdiocb); lpfc_els_free_iocb(phba, cmdiocb);
} }
/**
* lpfc_issue_els_flogi: Issue an flogi iocb command for a vport.
* @vport: pointer to a host virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
* @retry: number of retries to the command IOCB.
*
* This routine issues a Fabric Login (FLOGI) Request ELS command
* for a @vport. The initiator service parameters are put into the payload
* of the FLOGI Request IOCB and the top-level callback function pointer
* to lpfc_cmpl_els_flogi() routine is put to the IOCB completion callback
* function field. The lpfc_issue_fabric_iocb routine is invoked to send
* out FLOGI ELS command with one outstanding fabric IOCB at a time.
*
* Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
* will be incremented by 1 for holding the ndlp and the reference to ndlp
* will be stored into the context1 field of the IOCB for the completion
* callback function to the FLOGI ELS command.
*
* Return code
* 0 - successfully issued flogi iocb for @vport
* 1 - failed to issue flogi iocb for @vport
**/
static int static int
lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
uint8_t retry) uint8_t retry)
...@@ -694,6 +842,20 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -694,6 +842,20 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
return 0; return 0;
} }
/**
* lpfc_els_abort_flogi: Abort all outstanding flogi iocbs.
* @phba: pointer to lpfc hba data structure.
*
* This routine aborts all the outstanding Fabric Login (FLOGI) IOCBs
* with a @phba. This routine walks all the outstanding IOCBs on the txcmplq
* list and issues an abort IOCB commond on each outstanding IOCB that
* contains a active Fabric_DID ndlp. Note that this function is to issue
* the abort IOCB command on all the outstanding IOCBs, thus when this
* function returns, it does not guarantee all the IOCBs are actually aborted.
*
* Return code
* 0 - Sucessfully issued abort iocb on all outstanding flogis (Always 0)
**/
int int
lpfc_els_abort_flogi(struct lpfc_hba *phba) lpfc_els_abort_flogi(struct lpfc_hba *phba)
{ {
...@@ -729,6 +891,22 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba) ...@@ -729,6 +891,22 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba)
return 0; return 0;
} }
/**
* lpfc_initial_flogi: Issue an initial fabric login for a vport.
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine issues an initial Fabric Login (FLOGI) for the @vport
* specified. It first searches the ndlp with the Fabric_DID (0xfffffe) from
* the @vport's ndlp list. If no such ndlp found, it will create an ndlp and
* put it into the @vport's ndlp list. If an inactive ndlp found on the list,
* it will just be enabled and made active. The lpfc_issue_els_flogi() routine
* is then invoked with the @vport and the ndlp to perform the FLOGI for the
* @vport.
*
* Return code
* 0 - failed to issue initial flogi for @vport
* 1 - successfully issued initial flogi for @vport
**/
int int
lpfc_initial_flogi(struct lpfc_vport *vport) lpfc_initial_flogi(struct lpfc_vport *vport)
{ {
...@@ -764,6 +942,22 @@ lpfc_initial_flogi(struct lpfc_vport *vport) ...@@ -764,6 +942,22 @@ lpfc_initial_flogi(struct lpfc_vport *vport)
return 1; return 1;
} }
/**
* lpfc_initial_fdisc: Issue an initial fabric discovery for a vport.
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine issues an initial Fabric Discover (FDISC) for the @vport
* specified. It first searches the ndlp with the Fabric_DID (0xfffffe) from
* the @vport's ndlp list. If no such ndlp found, it will create an ndlp and
* put it into the @vport's ndlp list. If an inactive ndlp found on the list,
* it will just be enabled and made active. The lpfc_issue_els_fdisc() routine
* is then invoked with the @vport and the ndlp to perform the FDISC for the
* @vport.
*
* Return code
* 0 - failed to issue initial fdisc for @vport
* 1 - successfully issued initial fdisc for @vport
**/
int int
lpfc_initial_fdisc(struct lpfc_vport *vport) lpfc_initial_fdisc(struct lpfc_vport *vport)
{ {
...@@ -797,6 +991,17 @@ lpfc_initial_fdisc(struct lpfc_vport *vport) ...@@ -797,6 +991,17 @@ lpfc_initial_fdisc(struct lpfc_vport *vport)
return 1; return 1;
} }
/**
* lpfc_more_plogi: Check and issue remaining plogis for a vport.
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine checks whether there are more remaining Port Logins
* (PLOGI) to be issued for the @vport. If so, it will invoke the routine
* lpfc_els_disc_plogi() to go through the Node Port Recovery (NPR) nodes
* to issue ELS PLOGIs up to the configured discover threads with the
* @vport (@vport->cfg_discovery_threads). The function also decrement
* the @vport's num_disc_node by 1 if it is not already 0.
**/
void void
lpfc_more_plogi(struct lpfc_vport *vport) lpfc_more_plogi(struct lpfc_vport *vport)
{ {
...@@ -819,6 +1024,37 @@ lpfc_more_plogi(struct lpfc_vport *vport) ...@@ -819,6 +1024,37 @@ lpfc_more_plogi(struct lpfc_vport *vport)
return; return;
} }
/**
* lpfc_plogi_confirm_nport: Confirm pologi wwpn matches stored ndlp.
* @phba: pointer to lpfc hba data structure.
* @prsp: pointer to response IOCB payload.
* @ndlp: pointer to a node-list data structure.
*
* This routine checks and indicates whether the WWPN of an N_Port, retrieved
* from a PLOGI, matches the WWPN that is stored in the @ndlp for that N_POrt.
* The following cases are considered N_Port confirmed:
* 1) The N_Port is a Fabric ndlp; 2) The @ndlp is on vport list and matches
* the WWPN of the N_Port logged into; 3) The @ndlp is not on vport list but
* it does not have WWPN assigned either. If the WWPN is confirmed, the
* pointer to the @ndlp will be returned. If the WWPN is not confirmed:
* 1) if there is a node on vport list other than the @ndlp with the same
* WWPN of the N_Port PLOGI logged into, the lpfc_unreg_rpi() will be invoked
* on that node to release the RPI associated with the node; 2) if there is
* no node found on vport list with the same WWPN of the N_Port PLOGI logged
* into, a new node shall be allocated (or activated). In either case, the
* parameters of the @ndlp shall be copied to the new_ndlp, the @ndlp shall
* be released and the new_ndlp shall be put on to the vport node list and
* its pointer returned as the confirmed node.
*
* Note that before the @ndlp got "released", the keepDID from not-matching
* or inactive "new_ndlp" on the vport node list is assigned to the nlp_DID
* of the @ndlp. This is because the release of @ndlp is actually to put it
* into an inactive state on the vport node list and the vport node list
* management algorithm does not allow two node with a same DID.
*
* Return code
* pointer to the PLOGI N_Port @ndlp
**/
static struct lpfc_nodelist * static struct lpfc_nodelist *
lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
struct lpfc_nodelist *ndlp) struct lpfc_nodelist *ndlp)
...@@ -922,6 +1158,17 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, ...@@ -922,6 +1158,17 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
return new_ndlp; return new_ndlp;
} }
/**
* lpfc_end_rscn: Check and handle more rscn for a vport.
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine checks whether more Registration State Change
* Notifications (RSCNs) came in while the discovery state machine was in
* the FC_RSCN_MODE. If so, the lpfc_els_handle_rscn() routine will be
* invoked to handle the additional RSCNs for the @vport. Otherwise, the
* FC_RSCN_MODE bit will be cleared with the @vport to mark as the end of
* handling the RSCNs.
**/
void void
lpfc_end_rscn(struct lpfc_vport *vport) lpfc_end_rscn(struct lpfc_vport *vport)
{ {
...@@ -943,6 +1190,26 @@ lpfc_end_rscn(struct lpfc_vport *vport) ...@@ -943,6 +1190,26 @@ lpfc_end_rscn(struct lpfc_vport *vport)
} }
} }
/**
* lpfc_cmpl_els_plogi: Completion callback function for plogi.
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
*
* This routine is the completion callback function for issuing the Port
* Login (PLOGI) command. For PLOGI completion, there must be an active
* ndlp on the vport node list that matches the remote node ID from the
* PLOGI reponse IOCB. If such ndlp does not exist, the PLOGI is simply
* ignored and command IOCB released. The PLOGI response IOCB status is
* checked for error conditons. If there is error status reported, PLOGI
* retry shall be attempted by invoking the lpfc_els_retry() routine.
* Otherwise, the lpfc_plogi_confirm_nport() routine shall be invoked on
* the ndlp and the NLP_EVT_CMPL_PLOGI state to the Discover State Machine
* (DSM) is set for this PLOGI completion. Finally, it checks whether
* there are additional N_Port nodes with the vport that need to perform
* PLOGI. If so, the lpfc_more_plogi() routine is invoked to issue addition
* PLOGIs.
**/
static void static void
lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb) struct lpfc_iocbq *rspiocb)
...@@ -1048,6 +1315,27 @@ out: ...@@ -1048,6 +1315,27 @@ out:
return; return;
} }
/**
* lpfc_issue_els_plogi: Issue an plogi iocb command for a vport.
* @vport: pointer to a host virtual N_Port data structure.
* @did: destination port identifier.
* @retry: number of retries to the command IOCB.
*
* This routine issues a Port Login (PLOGI) command to a remote N_Port
* (with the @did) for a @vport. Before issuing a PLOGI to a remote N_Port,
* the ndlp with the remote N_Port DID must exist on the @vport's ndlp list.
* This routine constructs the proper feilds of the PLOGI IOCB and invokes
* the lpfc_sli_issue_iocb() routine to send out PLOGI ELS command.
*
* Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
* will be incremented by 1 for holding the ndlp and the reference to ndlp
* will be stored into the context1 field of the IOCB for the completion
* callback function to the PLOGI ELS command.
*
* Return code
* 0 - Successfully issued a plogi for @vport
* 1 - failed to issue a plogi for @vport
**/
int int
lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry) lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
{ {
...@@ -1106,6 +1394,19 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry) ...@@ -1106,6 +1394,19 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
return 0; return 0;
} }
/**
* lpfc_cmpl_els_prli: Completion callback function for prli.
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
*
* This routine is the completion callback function for a Process Login
* (PRLI) ELS command. The PRLI response IOCB status is checked for error
* status. If there is error status reported, PRLI retry shall be attempted
* by invoking the lpfc_els_retry() routine. Otherwise, the state
* NLP_EVT_CMPL_PRLI is sent to the Discover State Machine (DSM) for this
* ndlp to mark the PRLI completion.
**/
static void static void
lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb) struct lpfc_iocbq *rspiocb)
...@@ -1164,6 +1465,27 @@ out: ...@@ -1164,6 +1465,27 @@ out:
return; return;
} }
/**
* lpfc_issue_els_prli: Issue a prli iocb command for a vport.
* @vport: pointer to a host virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
* @retry: number of retries to the command IOCB.
*
* This routine issues a Process Login (PRLI) ELS command for the
* @vport. The PRLI service parameters are set up in the payload of the
* PRLI Request command and the pointer to lpfc_cmpl_els_prli() routine
* is put to the IOCB completion callback func field before invoking the
* routine lpfc_sli_issue_iocb() to send out PRLI command.
*
* Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
* will be incremented by 1 for holding the ndlp and the reference to ndlp
* will be stored into the context1 field of the IOCB for the completion
* callback function to the PRLI ELS command.
*
* Return code
* 0 - successfully issued prli iocb command for @vport
* 1 - failed to issue prli iocb command for @vport
**/
int int
lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
uint8_t retry) uint8_t retry)
...@@ -1233,6 +1555,15 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -1233,6 +1555,15 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
return 0; return 0;
} }
/**
* lpfc_more_adisc: Issue more adisc as needed.
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine determines whether there are more ndlps on a @vport
* node list need to have Address Discover (ADISC) issued. If so, it will
* invoke the lpfc_els_disc_adisc() routine to issue ADISC on the @vport's
* remaining nodes which need to have ADISC sent.
**/
void void
lpfc_more_adisc(struct lpfc_vport *vport) lpfc_more_adisc(struct lpfc_vport *vport)
{ {
...@@ -1255,6 +1586,18 @@ lpfc_more_adisc(struct lpfc_vport *vport) ...@@ -1255,6 +1586,18 @@ lpfc_more_adisc(struct lpfc_vport *vport)
return; return;
} }
/**
* lpfc_rscn_disc: Perform rscn discovery for a vport.
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine performs Registration State Change Notification (RSCN)
* discovery for a @vport. If the @vport's node port recovery count is not
* zero, it will invoke the lpfc_els_disc_plogi() to perform PLOGI for all
* the nodes that need recovery. If none of the PLOGI were needed through
* the lpfc_els_disc_plogi() routine, the lpfc_end_rscn() routine shall be
* invoked to check and handle possible more RSCN came in during the period
* of processing the current ones.
**/
static void static void
lpfc_rscn_disc(struct lpfc_vport *vport) lpfc_rscn_disc(struct lpfc_vport *vport)
{ {
...@@ -1269,6 +1612,22 @@ lpfc_rscn_disc(struct lpfc_vport *vport) ...@@ -1269,6 +1612,22 @@ lpfc_rscn_disc(struct lpfc_vport *vport)
lpfc_end_rscn(vport); lpfc_end_rscn(vport);
} }
/**
* lpfc_cmpl_els_adisc: Completion callback function for adisc.
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
*
* This routine is the completion function for issuing the Address Discover
* (ADISC) command. It first checks to see whether link went down during
* the discovery process. If so, the node will be marked as node port
* recovery for issuing discover IOCB by the link attention handler and
* exit. Otherwise, the response status is checked. If error was reported
* in the response status, the ADISC command shall be retried by invoking
* the lpfc_els_retry() routine. Otherwise, if no error was reported in
* the response status, the state machine is invoked to set transition
* with respect to NLP_EVT_CMPL_ADISC event.
**/
static void static void
lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb) struct lpfc_iocbq *rspiocb)
...@@ -1384,6 +1743,26 @@ out: ...@@ -1384,6 +1743,26 @@ out:
return; return;
} }
/**
* lpfc_issue_els_adisc: Issue an address discover iocb to an node on a vport.
* @vport: pointer to a virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
* @retry: number of retries to the command IOCB.
*
* This routine issues an Address Discover (ADISC) for an @ndlp on a
* @vport. It prepares the payload of the ADISC ELS command, updates the
* and states of the ndlp, and invokes the lpfc_sli_issue_iocb() routine
* to issue the ADISC ELS command.
*
* Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
* will be incremented by 1 for holding the ndlp and the reference to ndlp
* will be stored into the context1 field of the IOCB for the completion
* callback function to the ADISC ELS command.
*
* Return code
* 0 - successfully issued adisc
* 1 - failed to issue adisc
**/
int int
lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
uint8_t retry) uint8_t retry)
...@@ -1437,6 +1816,18 @@ lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -1437,6 +1816,18 @@ lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
return 0; return 0;
} }
/**
* lpfc_cmpl_els_logo: Completion callback function for logo.
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
*
* This routine is the completion function for issuing the ELS Logout (LOGO)
* command. If no error status was reported from the LOGO response, the
* state machine of the associated ndlp shall be invoked for transition with
* respect to NLP_EVT_CMPL_LOGO event. Otherwise, if error status was reported,
* the lpfc_els_retry() routine will be invoked to retry the LOGO command.
**/
static void static void
lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb) struct lpfc_iocbq *rspiocb)
...@@ -1502,6 +1893,26 @@ out: ...@@ -1502,6 +1893,26 @@ out:
return; return;
} }
/**
* lpfc_issue_els_logo: Issue a logo to an node on a vport.
* @vport: pointer to a virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
* @retry: number of retries to the command IOCB.
*
* This routine constructs and issues an ELS Logout (LOGO) iocb command
* to a remote node, referred by an @ndlp on a @vport. It constructs the
* payload of the IOCB, properly sets up the @ndlp state, and invokes the
* lpfc_sli_issue_iocb() routine to send out the LOGO ELS command.
*
* Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
* will be incremented by 1 for holding the ndlp and the reference to ndlp
* will be stored into the context1 field of the IOCB for the completion
* callback function to the LOGO ELS command.
*
* Return code
* 0 - successfully issued logo
* 1 - failed to issue logo
**/
int int
lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
uint8_t retry) uint8_t retry)
...@@ -1563,6 +1974,22 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -1563,6 +1974,22 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
return 0; return 0;
} }
/**
* lpfc_cmpl_els_cmd: Completion callback function for generic els command.
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
*
* This routine is a generic completion callback function for ELS commands.
* Specifically, it is the callback function which does not need to perform
* any command specific operations. It is currently used by the ELS command
* issuing routines for the ELS State Change Request (SCR),
* lpfc_issue_els_scr(), and the ELS Fibre Channel Address Resolution
* Protocol Response (FARPR) routine, lpfc_issue_els_farpr(). Other than
* certain debug loggings, this callback function simply invokes the
* lpfc_els_chk_latt() routine to check whether link went down during the
* discovery process.
**/
static void static void
lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb) struct lpfc_iocbq *rspiocb)
...@@ -1587,6 +2014,28 @@ lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -1587,6 +2014,28 @@ lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
return; return;
} }
/**
* lpfc_issue_els_scr: Issue a scr to an node on a vport.
* @vport: pointer to a host virtual N_Port data structure.
* @nportid: N_Port identifier to the remote node.
* @retry: number of retries to the command IOCB.
*
* This routine issues a State Change Request (SCR) to a fabric node
* on a @vport. The remote node @nportid is passed into the function. It
* first search the @vport node list to find the matching ndlp. If no such
* ndlp is found, a new ndlp shall be created for this (SCR) purpose. An
* IOCB is allocated, payload prepared, and the lpfc_sli_issue_iocb()
* routine is invoked to send the SCR IOCB.
*
* Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
* will be incremented by 1 for holding the ndlp and the reference to ndlp
* will be stored into the context1 field of the IOCB for the completion
* callback function to the SCR ELS command.
*
* Return code
* 0 - Successfully issued scr command
* 1 - Failed to issue scr command
**/
int int
lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
{ {
...@@ -1659,6 +2108,28 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) ...@@ -1659,6 +2108,28 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
return 0; return 0;
} }
/**
* lpfc_issue_els_farpr: Issue a farp to an node on a vport.
* @vport: pointer to a host virtual N_Port data structure.
* @nportid: N_Port identifier to the remote node.
* @retry: number of retries to the command IOCB.
*
* This routine issues a Fibre Channel Address Resolution Response
* (FARPR) to a node on a vport. The remote node N_Port identifier (@nportid)
* is passed into the function. It first search the @vport node list to find
* the matching ndlp. If no such ndlp is found, a new ndlp shall be created
* for this (FARPR) purpose. An IOCB is allocated, payload prepared, and the
* lpfc_sli_issue_iocb() routine is invoked to send the FARPR ELS command.
*
* Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
* will be incremented by 1 for holding the ndlp and the reference to ndlp
* will be stored into the context1 field of the IOCB for the completion
* callback function to the PARPR ELS command.
*
* Return code
* 0 - Successfully issued farpr command
* 1 - Failed to issue farpr command
**/
static int static int
lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
{ {
...@@ -1748,6 +2219,18 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) ...@@ -1748,6 +2219,18 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
return 0; return 0;
} }
/**
* lpfc_cancel_retry_delay_tmo: Cancel the timer with delayed iocb-cmd retry.
* @vport: pointer to a host virtual N_Port data structure.
* @nlp: pointer to a node-list data structure.
*
* This routine cancels the timer with a delayed IOCB-command retry for
* a @vport's @ndlp. It stops the timer for the delayed function retrial and
* removes the ELS retry event if it presents. In addition, if the
* NLP_NPR_2B_DISC bit is set in the @nlp's nlp_flag bitmap, ADISC IOCB
* commands are sent for the @vport's nodes that require issuing discovery
* ADISC.
**/
void void
lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp) lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp)
{ {
...@@ -1794,6 +2277,20 @@ lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp) ...@@ -1794,6 +2277,20 @@ lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp)
return; return;
} }
/**
* lpfc_els_retry_delay: Timer function with a ndlp delayed function timer.
* @ptr: holder for the pointer to the timer function associated data (ndlp).
*
* This routine is invoked by the ndlp delayed-function timer to check
* whether there is any pending ELS retry event(s) with the node. If not, it
* simply returns. Otherwise, if there is at least one ELS delayed event, it
* adds the delayed events to the HBA work list and invokes the
* lpfc_worker_wake_up() routine to wake up worker thread to process the
* event. Note that lpfc_nlp_get() is called before posting the event to
* the work list to hold reference count of ndlp so that it guarantees the
* reference to ndlp will still be available when the worker thread gets
* to the event associated with the ndlp.
**/
void void
lpfc_els_retry_delay(unsigned long ptr) lpfc_els_retry_delay(unsigned long ptr)
{ {
...@@ -1822,6 +2319,15 @@ lpfc_els_retry_delay(unsigned long ptr) ...@@ -1822,6 +2319,15 @@ lpfc_els_retry_delay(unsigned long ptr)
return; return;
} }
/**
* lpfc_els_retry_delay_handler: Work thread handler for ndlp delayed function.
* @ndlp: pointer to a node-list data structure.
*
* This routine is the worker-thread handler for processing the @ndlp delayed
* event(s), posted by the lpfc_els_retry_delay() routine. It simply retrieves
* the last ELS command from the associated ndlp and invokes the proper ELS
* function according to the delayed ELS command to retry the command.
**/
void void
lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp) lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp)
{ {
...@@ -1884,6 +2390,27 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp) ...@@ -1884,6 +2390,27 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp)
return; return;
} }
/**
* lpfc_els_retry: Make retry decision on an els command iocb.
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
*
* This routine makes a retry decision on an ELS command IOCB, which has
* failed. The following ELS IOCBs use this function for retrying the command
* when previously issued command responsed with error status: FLOGI, PLOGI,
* PRLI, ADISC, LOGO, and FDISC. Based on the ELS command type and the
* returned error status, it makes the decision whether a retry shall be
* issued for the command, and whether a retry shall be made immediately or
* delayed. In the former case, the corresponding ELS command issuing-function
* is called to retry the command. In the later case, the ELS command shall
* be posted to the ndlp delayed event and delayed function timer set to the
* ndlp for the delayed command issusing.
*
* Return code
* 0 - No retry of els command is made
* 1 - Immediate or delayed retry of els command is made
**/
static int static int
lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb) struct lpfc_iocbq *rspiocb)
...@@ -2182,12 +2709,26 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -2182,12 +2709,26 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
return 0; return 0;
} }
/**
* lpfc_els_free_data: Free lpfc dma buffer and data structure with an iocb.
* @phba: pointer to lpfc hba data structure.
* @buf_ptr1: pointer to the lpfc DMA buffer data structure.
*
* This routine releases the lpfc DMA (Direct Memory Access) buffer(s)
* associated with a command IOCB back to the lpfc DMA buffer pool. It first
* checks to see whether there is a lpfc DMA buffer associated with the
* response of the command IOCB. If so, it will be released before releasing
* the lpfc DMA buffer associated with the IOCB itself.
*
* Return code
* 0 - Successfully released lpfc DMA buffer (currently, always return 0)
**/
static int static int
lpfc_els_free_data(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr1) lpfc_els_free_data(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr1)
{ {
struct lpfc_dmabuf *buf_ptr; struct lpfc_dmabuf *buf_ptr;
/* Free the response before processing the command. */ /* Free the response before processing the command. */
if (!list_empty(&buf_ptr1->list)) { if (!list_empty(&buf_ptr1->list)) {
list_remove_head(&buf_ptr1->list, buf_ptr, list_remove_head(&buf_ptr1->list, buf_ptr,
struct lpfc_dmabuf, struct lpfc_dmabuf,
...@@ -2200,6 +2741,18 @@ lpfc_els_free_data(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr1) ...@@ -2200,6 +2741,18 @@ lpfc_els_free_data(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr1)
return 0; return 0;
} }
/**
* lpfc_els_free_bpl: Free lpfc dma buffer and data structure with bpl.
* @phba: pointer to lpfc hba data structure.
* @buf_ptr: pointer to the lpfc dma buffer data structure.
*
* This routine releases the lpfc Direct Memory Access (DMA) buffer
* associated with a Buffer Pointer List (BPL) back to the lpfc DMA buffer
* pool.
*
* Return code
* 0 - Successfully released lpfc DMA buffer (currently, always return 0)
**/
static int static int
lpfc_els_free_bpl(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr) lpfc_els_free_bpl(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr)
{ {
...@@ -2208,6 +2761,33 @@ lpfc_els_free_bpl(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr) ...@@ -2208,6 +2761,33 @@ lpfc_els_free_bpl(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr)
return 0; return 0;
} }
/**
* lpfc_els_free_iocb: Free a command iocb and its associated resources.
* @phba: pointer to lpfc hba data structure.
* @elsiocb: pointer to lpfc els command iocb data structure.
*
* This routine frees a command IOCB and its associated resources. The
* command IOCB data structure contains the reference to various associated
* resources, these fields must be set to NULL if the associated reference
* not present:
* context1 - reference to ndlp
* context2 - reference to cmd
* context2->next - reference to rsp
* context3 - reference to bpl
*
* It first properly decrements the reference count held on ndlp for the
* IOCB completion callback function. If LPFC_DELAY_MEM_FREE flag is not
* set, it invokes the lpfc_els_free_data() routine to release the Direct
* Memory Access (DMA) buffers associated with the IOCB. Otherwise, it
* adds the DMA buffer the @phba data structure for the delayed release.
* If reference to the Buffer Pointer List (BPL) is present, the
* lpfc_els_free_bpl() routine is invoked to release the DMA memory
* associated with BPL. Finally, the lpfc_sli_release_iocbq() routine is
* invoked to release the IOCB data structure back to @phba IOCBQ list.
*
* Return code
* 0 - Success (currently, always return 0)
**/
int int
lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb) lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb)
{ {
...@@ -2274,6 +2854,23 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb) ...@@ -2274,6 +2854,23 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb)
return 0; return 0;
} }
/**
* lpfc_cmpl_els_logo_acc: Completion callback function to logo acc response.
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
*
* This routine is the completion callback function to the Logout (LOGO)
* Accept (ACC) Response ELS command. This routine is invoked to indicate
* the completion of the LOGO process. It invokes the lpfc_nlp_not_used() to
* release the ndlp if it has the last reference remaining (reference count
* is 1). If succeeded (meaning ndlp released), it sets the IOCB context1
* field to NULL to inform the following lpfc_els_free_iocb() routine no
* ndlp reference count needs to be decremented. Otherwise, the ndlp
* reference use-count shall be decremented by the lpfc_els_free_iocb()
* routine. Finally, the lpfc_els_free_iocb() is invoked to release the
* IOCB data structure.
**/
static void static void
lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb) struct lpfc_iocbq *rspiocb)
...@@ -2311,6 +2908,19 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -2311,6 +2908,19 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
return; return;
} }
/**
* lpfc_mbx_cmpl_dflt_rpi: Completion callbk func for unreg dflt rpi mbox cmd.
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
* This routine is the completion callback function for unregister default
* RPI (Remote Port Index) mailbox command to the @phba. It simply releases
* the associated lpfc Direct Memory Access (DMA) buffer back to the pool and
* decrements the ndlp reference count held for this completion callback
* function. After that, it invokes the lpfc_nlp_not_used() to check
* whether there is only one reference left on the ndlp. If so, it will
* perform one more decrement and trigger the release of the ndlp.
**/
void void
lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{ {
...@@ -2332,6 +2942,22 @@ lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -2332,6 +2942,22 @@ lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
return; return;
} }
/**
* lpfc_cmpl_els_rsp: Completion callback function for els response iocb cmd.
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
*
* This routine is the completion callback function for ELS Response IOCB
* command. In normal case, this callback function just properly sets the
* nlp_flag bitmap in the ndlp data structure, if the mbox command reference
* field in the command IOCB is not NULL, the referred mailbox command will
* be send out, and then invokes the lpfc_els_free_iocb() routine to release
* the IOCB. Under error conditions, such as when a LS_RJT is returned or a
* link down event occurred during the discovery, the lpfc_nlp_not_used()
* routine shall be invoked trying to release the ndlp if no other threads
* are currently referring it.
**/
static void static void
lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb) struct lpfc_iocbq *rspiocb)
...@@ -2487,6 +3113,31 @@ out: ...@@ -2487,6 +3113,31 @@ out:
return; return;
} }
/**
* lpfc_els_rsp_acc: Prepare and issue an acc response iocb command.
* @vport: pointer to a host virtual N_Port data structure.
* @flag: the els command code to be accepted.
* @oldiocb: pointer to the original lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
* @mbox: pointer to the driver internal queue element for mailbox command.
*
* This routine prepares and issues an Accept (ACC) response IOCB
* command. It uses the @flag to properly set up the IOCB field for the
* specific ACC response command to be issued and invokes the
* lpfc_sli_issue_iocb() routine to send out ACC response IOCB. If a
* @mbox pointer is passed in, it will be put into the context_un.mbox
* field of the IOCB for the completion callback function to issue the
* mailbox command to the HBA later when callback is invoked.
*
* Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
* will be incremented by 1 for holding the ndlp and the reference to ndlp
* will be stored into the context1 field of the IOCB for the completion
* callback function to the corresponding response ELS IOCB command.
*
* Return code
* 0 - Successfully issued acc response
* 1 - Failed to issue acc response
**/
int int
lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp, struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp,
...@@ -2601,6 +3252,28 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, ...@@ -2601,6 +3252,28 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
return 0; return 0;
} }
/**
* lpfc_els_rsp_reject: Propare and issue a rjt response iocb command.
* @vport: pointer to a virtual N_Port data structure.
* @rejectError:
* @oldiocb: pointer to the original lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
* @mbox: pointer to the driver internal queue element for mailbox command.
*
* This routine prepares and issue an Reject (RJT) response IOCB
* command. If a @mbox pointer is passed in, it will be put into the
* context_un.mbox field of the IOCB for the completion callback function
* to issue to the HBA later.
*
* Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
* will be incremented by 1 for holding the ndlp and the reference to ndlp
* will be stored into the context1 field of the IOCB for the completion
* callback function to the reject response ELS IOCB command.
*
* Return code
* 0 - Successfully issued reject response
* 1 - Failed to issue reject response
**/
int int
lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp, struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp,
...@@ -2660,6 +3333,25 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, ...@@ -2660,6 +3333,25 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
return 0; return 0;
} }
/**
* lpfc_els_rsp_adisc_acc: Prepare and issue acc response to adisc iocb cmd.
* @vport: pointer to a virtual N_Port data structure.
* @oldiocb: pointer to the original lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
*
* This routine prepares and issues an Accept (ACC) response to Address
* Discover (ADISC) ELS command. It simply prepares the payload of the IOCB
* and invokes the lpfc_sli_issue_iocb() routine to send out the command.
*
* Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
* will be incremented by 1 for holding the ndlp and the reference to ndlp
* will be stored into the context1 field of the IOCB for the completion
* callback function to the ADISC Accept response ELS IOCB command.
*
* Return code
* 0 - Successfully issued acc adisc response
* 1 - Failed to issue adisc acc response
**/
int int
lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
struct lpfc_nodelist *ndlp) struct lpfc_nodelist *ndlp)
...@@ -2716,6 +3408,25 @@ lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, ...@@ -2716,6 +3408,25 @@ lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
return 0; return 0;
} }
/**
* lpfc_els_rsp_prli_acc: Prepare and issue acc response to prli iocb cmd.
* @vport: pointer to a virtual N_Port data structure.
* @oldiocb: pointer to the original lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
*
* This routine prepares and issues an Accept (ACC) response to Process
* Login (PRLI) ELS command. It simply prepares the payload of the IOCB
* and invokes the lpfc_sli_issue_iocb() routine to send out the command.
*
* Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
* will be incremented by 1 for holding the ndlp and the reference to ndlp
* will be stored into the context1 field of the IOCB for the completion
* callback function to the PRLI Accept response ELS IOCB command.
*
* Return code
* 0 - Successfully issued acc prli response
* 1 - Failed to issue acc prli response
**/
int int
lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
struct lpfc_nodelist *ndlp) struct lpfc_nodelist *ndlp)
...@@ -2795,6 +3506,32 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, ...@@ -2795,6 +3506,32 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
return 0; return 0;
} }
/**
* lpfc_els_rsp_rnid_acc: Issue rnid acc response iocb command.
* @vport: pointer to a virtual N_Port data structure.
* @format: rnid command format.
* @oldiocb: pointer to the original lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
*
* This routine issues a Request Node Identification Data (RNID) Accept
* (ACC) response. It constructs the RNID ACC response command according to
* the proper @format and then calls the lpfc_sli_issue_iocb() routine to
* issue the response. Note that this command does not need to hold the ndlp
* reference count for the callback. So, the ndlp reference count taken by
* the lpfc_prep_els_iocb() routine is put back and the context1 field of
* IOCB is set to NULL to indicate to the lpfc_els_free_iocb() routine that
* there is no ndlp reference available.
*
* Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
* will be incremented by 1 for holding the ndlp and the reference to ndlp
* will be stored into the context1 field of the IOCB for the completion
* callback function. However, for the RNID Accept Response ELS command,
* this is undone later by this routine after the IOCB is allocated.
*
* Return code
* 0 - Successfully issued acc rnid response
* 1 - Failed to issue acc rnid response
**/
static int static int
lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format, lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format,
struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp) struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp)
...@@ -2875,6 +3612,25 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format, ...@@ -2875,6 +3612,25 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format,
return 0; return 0;
} }
/**
* lpfc_els_disc_adisc: Issue remaining adisc iocbs to npr nodes of a vport.
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine issues Address Discover (ADISC) ELS commands to those
* N_Ports which are in node port recovery state and ADISC has not been issued
* for the @vport. Each time an ELS ADISC IOCB is issued by invoking the
* lpfc_issue_els_adisc() routine, the per @vport number of discover count
* (num_disc_nodes) shall be incremented. If the num_disc_nodes reaches a
* pre-configured threshold (cfg_discovery_threads), the @vport fc_flag will
* be marked with FC_NLP_MORE bit and the process of issuing remaining ADISC
* IOCBs quit for later pick up. On the other hand, after walking through
* all the ndlps with the @vport and there is none ADISC IOCB issued, the
* @vport fc_flag shall be cleared with FC_NLP_MORE bit indicating there is
* no more ADISC need to be sent.
*
* Return code
* The number of N_Ports with adisc issued.
**/
int int
lpfc_els_disc_adisc(struct lpfc_vport *vport) lpfc_els_disc_adisc(struct lpfc_vport *vport)
{ {
...@@ -2914,6 +3670,25 @@ lpfc_els_disc_adisc(struct lpfc_vport *vport) ...@@ -2914,6 +3670,25 @@ lpfc_els_disc_adisc(struct lpfc_vport *vport)
return sentadisc; return sentadisc;
} }
/**
* lpfc_els_disc_plogi: Issue plogi for all npr nodes of a vport before adisc.
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine issues Port Login (PLOGI) ELS commands to all the N_Ports
* which are in node port recovery state, with a @vport. Each time an ELS
* ADISC PLOGI IOCB is issued by invoking the lpfc_issue_els_plogi() routine,
* the per @vport number of discover count (num_disc_nodes) shall be
* incremented. If the num_disc_nodes reaches a pre-configured threshold
* (cfg_discovery_threads), the @vport fc_flag will be marked with FC_NLP_MORE
* bit set and quit the process of issuing remaining ADISC PLOGIN IOCBs for
* later pick up. On the other hand, after walking through all the ndlps with
* the @vport and there is none ADISC PLOGI IOCB issued, the @vport fc_flag
* shall be cleared with the FC_NLP_MORE bit indicating there is no more ADISC
* PLOGI need to be sent.
*
* Return code
* The number of N_Ports with plogi issued.
**/
int int
lpfc_els_disc_plogi(struct lpfc_vport *vport) lpfc_els_disc_plogi(struct lpfc_vport *vport)
{ {
...@@ -2954,6 +3729,15 @@ lpfc_els_disc_plogi(struct lpfc_vport *vport) ...@@ -2954,6 +3729,15 @@ lpfc_els_disc_plogi(struct lpfc_vport *vport)
return sentplogi; return sentplogi;
} }
/**
* lpfc_els_flush_rscn: Clean up any rscn activities with a vport.
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine cleans up any Registration State Change Notification
* (RSCN) activity with a @vport. Note that the fc_rscn_flush flag of the
* @vport together with the host_lock is used to prevent multiple thread
* trying to access the RSCN array on a same @vport at the same time.
**/
void void
lpfc_els_flush_rscn(struct lpfc_vport *vport) lpfc_els_flush_rscn(struct lpfc_vport *vport)
{ {
...@@ -2984,6 +3768,18 @@ lpfc_els_flush_rscn(struct lpfc_vport *vport) ...@@ -2984,6 +3768,18 @@ lpfc_els_flush_rscn(struct lpfc_vport *vport)
vport->fc_rscn_flush = 0; vport->fc_rscn_flush = 0;
} }
/**
* lpfc_rscn_payload_check: Check whether there is a pending rscn to a did.
* @vport: pointer to a host virtual N_Port data structure.
* @did: remote destination port identifier.
*
* This routine checks whether there is any pending Registration State
* Configuration Notification (RSCN) to a @did on @vport.
*
* Return code
* None zero - The @did matched with a pending rscn
* 0 - not able to match @did with a pending rscn
**/
int int
lpfc_rscn_payload_check(struct lpfc_vport *vport, uint32_t did) lpfc_rscn_payload_check(struct lpfc_vport *vport, uint32_t did)
{ {
...@@ -3053,6 +3849,17 @@ return_did_out: ...@@ -3053,6 +3849,17 @@ return_did_out:
return did; return did;
} }
/**
* lpfc_rscn_recovery_check: Send recovery event to vport nodes matching rscn
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine sends recovery (NLP_EVT_DEVICE_RECOVERY) event to the
* state machine for a @vport's nodes that are with pending RSCN (Registration
* State Change Notification).
*
* Return code
* 0 - Successful (currently alway return 0)
**/
static int static int
lpfc_rscn_recovery_check(struct lpfc_vport *vport) lpfc_rscn_recovery_check(struct lpfc_vport *vport)
{ {
...@@ -3071,6 +3878,28 @@ lpfc_rscn_recovery_check(struct lpfc_vport *vport) ...@@ -3071,6 +3878,28 @@ lpfc_rscn_recovery_check(struct lpfc_vport *vport)
return 0; return 0;
} }
/**
* lpfc_els_rcv_rscn: Process an unsolicited rscn iocb.
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
*
* This routine processes an unsolicited RSCN (Registration State Change
* Notification) IOCB. First, the payload of the unsolicited RSCN is walked
* to invoke fc_host_post_event() routine to the FC transport layer. If the
* discover state machine is about to begin discovery, it just accepts the
* RSCN and the discovery process will satisfy the RSCN. If this RSCN only
* contains N_Port IDs for other vports on this HBA, it just accepts the
* RSCN and ignore processing it. If the state machine is in the recovery
* state, the fc_rscn_id_list of this @vport is walked and the
* lpfc_rscn_recovery_check() routine is invoked to send recovery event for
* all nodes that match RSCN payload. Otherwise, the lpfc_els_handle_rscn()
* routine is invoked to handle the RSCN event.
*
* Return code
* 0 - Just sent the acc response
* 1 - Sent the acc response and waited for name server completion
**/
static int static int
lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *ndlp) struct lpfc_nodelist *ndlp)
...@@ -3241,6 +4070,22 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ...@@ -3241,6 +4070,22 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
return lpfc_els_handle_rscn(vport); return lpfc_els_handle_rscn(vport);
} }
/**
* lpfc_els_handle_rscn: Handle rscn for a vport.
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine handles the Registration State Configuration Notification
* (RSCN) for a @vport. If login to NameServer does not exist, a new ndlp shall
* be created and a Port Login (PLOGI) to the NameServer is issued. Otherwise,
* if the ndlp to NameServer exists, a Common Transport (CT) command to the
* NameServer shall be issued. If CT command to the NameServer fails to be
* issued, the lpfc_els_flush_rscn() routine shall be invoked to clean up any
* RSCN activities with the @vport.
*
* Return code
* 0 - Cleaned up rscn on the @vport
* 1 - Wait for plogi to name server before proceed
**/
int int
lpfc_els_handle_rscn(struct lpfc_vport *vport) lpfc_els_handle_rscn(struct lpfc_vport *vport)
{ {
...@@ -3313,6 +4158,31 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport) ...@@ -3313,6 +4158,31 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport)
return 0; return 0;
} }
/**
* lpfc_els_rcv_flogi: Process an unsolicited flogi iocb.
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
*
* This routine processes Fabric Login (FLOGI) IOCB received as an ELS
* unsolicited event. An unsolicited FLOGI can be received in a point-to-
* point topology. As an unsolicited FLOGI should not be received in a loop
* mode, any unsolicited FLOGI received in loop mode shall be ignored. The
* lpfc_check_sparm() routine is invoked to check the parameters in the
* unsolicited FLOGI. If parameters validation failed, the routine
* lpfc_els_rsp_reject() shall be called with reject reason code set to
* LSEXP_SPARM_OPTIONS to reject the FLOGI. Otherwise, the Port WWN in the
* FLOGI shall be compared with the Port WWN of the @vport to determine who
* will initiate PLOGI. The higher lexicographical value party shall has
* higher priority (as the winning port) and will initiate PLOGI and
* communicate Port_IDs (Addresses) for both nodes in PLOGI. The result
* of this will be marked in the @vport fc_flag field with FC_PT2PT_PLOGI
* and then the lpfc_els_rsp_acc() routine is invoked to accept the FLOGI.
*
* Return code
* 0 - Successfully processed the unsolicited flogi
* 1 - Failed to process the unsolicited flogi
**/
static int static int
lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *ndlp) struct lpfc_nodelist *ndlp)
...@@ -3402,6 +4272,22 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ...@@ -3402,6 +4272,22 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
return 0; return 0;
} }
/**
* lpfc_els_rcv_rnid: Process an unsolicited rnid iocb.
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
*
* This routine processes Request Node Identification Data (RNID) IOCB
* received as an ELS unsolicited event. Only when the RNID specified format
* 0x0 or 0xDF (Topology Discovery Specific Node Identification Data)
* present, this routine will invoke the lpfc_els_rsp_rnid_acc() routine to
* Accept (ACC) the RNID ELS command. All the other RNID formats are
* rejected by invoking the lpfc_els_rsp_reject() routine.
*
* Return code
* 0 - Successfully processed rnid iocb (currently always return 0)
**/
static int static int
lpfc_els_rcv_rnid(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, lpfc_els_rcv_rnid(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *ndlp) struct lpfc_nodelist *ndlp)
...@@ -3441,6 +4327,19 @@ lpfc_els_rcv_rnid(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ...@@ -3441,6 +4327,19 @@ lpfc_els_rcv_rnid(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
return 0; return 0;
} }
/**
* lpfc_els_rcv_lirr: Process an unsolicited lirr iocb.
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
*
* This routine processes a Link Incident Report Registration(LIRR) IOCB
* received as an ELS unsolicited event. Currently, this function just invokes
* the lpfc_els_rsp_reject() routine to reject the LIRR IOCB unconditionally.
*
* Return code
* 0 - Successfully processed lirr iocb (currently always return 0)
**/
static int static int
lpfc_els_rcv_lirr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, lpfc_els_rcv_lirr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *ndlp) struct lpfc_nodelist *ndlp)
...@@ -3456,6 +4355,25 @@ lpfc_els_rcv_lirr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ...@@ -3456,6 +4355,25 @@ lpfc_els_rcv_lirr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
return 0; return 0;
} }
/**
* lpfc_els_rsp_rps_acc: Completion callbk func for MBX_READ_LNK_STAT mbox cmd.
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
* This routine is the completion callback function for the MBX_READ_LNK_STAT
* mailbox command. This callback function is to actually send the Accept
* (ACC) response to a Read Port Status (RPS) unsolicited IOCB event. It
* collects the link statistics from the completion of the MBX_READ_LNK_STAT
* mailbox command, constructs the RPS response with the link statistics
* collected, and then invokes the lpfc_sli_issue_iocb() routine to send ACC
* response to the RPS.
*
* Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
* will be incremented by 1 for holding the ndlp and the reference to ndlp
* will be stored into the context1 field of the IOCB for the completion
* callback function to the RPS Accept Response ELS IOCB command.
*
**/
static void static void
lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{ {
...@@ -3531,6 +4449,24 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -3531,6 +4449,24 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
return; return;
} }
/**
* lpfc_els_rcv_rps: Process an unsolicited rps iocb.
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
*
* This routine processes Read Port Status (RPS) IOCB received as an
* ELS unsolicited event. It first checks the remote port state. If the
* remote port is not in NLP_STE_UNMAPPED_NODE state or NLP_STE_MAPPED_NODE
* state, it invokes the lpfc_els_rsp_reject() routine to send the reject
* response. Otherwise, it issue the MBX_READ_LNK_STAT mailbox command
* for reading the HBA link statistics. It is for the callback function,
* lpfc_els_rsp_rps_acc(), set to the MBX_READ_LNK_STAT mailbox command
* to actually sending out RPS Accept (ACC) response.
*
* Return codes
* 0 - Successfully processed rps iocb (currently always return 0)
**/
static int static int
lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *ndlp) struct lpfc_nodelist *ndlp)
...@@ -3592,6 +4528,25 @@ lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ...@@ -3592,6 +4528,25 @@ lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
return 0; return 0;
} }
/**
* lpfc_els_rsp_rpl_acc: Issue an accept rpl els command.
* @vport: pointer to a host virtual N_Port data structure.
* @cmdsize: size of the ELS command.
* @oldiocb: pointer to the original lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
*
* This routine issuees an Accept (ACC) Read Port List (RPL) ELS command.
* It is to be called by the lpfc_els_rcv_rpl() routine to accept the RPL.
*
* Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
* will be incremented by 1 for holding the ndlp and the reference to ndlp
* will be stored into the context1 field of the IOCB for the completion
* callback function to the RPL Accept Response ELS command.
*
* Return code
* 0 - Successfully issued ACC RPL ELS command
* 1 - Failed to issue ACC RPL ELS command
**/
static int static int
lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize, lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize,
struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp) struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp)
...@@ -3645,6 +4600,22 @@ lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize, ...@@ -3645,6 +4600,22 @@ lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize,
return 0; return 0;
} }
/**
* lpfc_els_rcv_rpl: Process an unsolicited rpl iocb.
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
*
* This routine processes Read Port List (RPL) IOCB received as an ELS
* unsolicited event. It first checks the remote port state. If the remote
* port is not in NLP_STE_UNMAPPED_NODE and NLP_STE_MAPPED_NODE states, it
* invokes the lpfc_els_rsp_reject() routine to send reject response.
* Otherwise, this routine then invokes the lpfc_els_rsp_rpl_acc() routine
* to accept the RPL.
*
* Return code
* 0 - Successfully processed rpl iocb (currently always return 0)
**/
static int static int
lpfc_els_rcv_rpl(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, lpfc_els_rcv_rpl(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *ndlp) struct lpfc_nodelist *ndlp)
...@@ -3685,6 +4656,30 @@ lpfc_els_rcv_rpl(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ...@@ -3685,6 +4656,30 @@ lpfc_els_rcv_rpl(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
return 0; return 0;
} }
/**
* lpfc_els_rcv_farp: Process an unsolicited farp request els command.
* @vport: pointer to a virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
*
* This routine processes Fibre Channel Address Resolution Protocol
* (FARP) Request IOCB received as an ELS unsolicited event. Currently,
* the lpfc driver only supports matching on WWPN or WWNN for FARP. As such,
* FARP_MATCH_PORT flag and FARP_MATCH_NODE flag are checked against the
* Match Flag in the FARP request IOCB: if FARP_MATCH_PORT flag is set, the
* remote PortName is compared against the FC PortName stored in the @vport
* data structure; if FARP_MATCH_NODE flag is set, the remote NodeName is
* compared against the FC NodeName stored in the @vport data structure.
* If any of these matches and the FARP_REQUEST_FARPR flag is set in the
* FARP request IOCB Response Flag, the lpfc_issue_els_farpr() routine is
* invoked to send out FARP Response to the remote node. Before sending the
* FARP Response, however, the FARP_REQUEST_PLOGI flag is check in the FARP
* request IOCB Response Flag and, if it is set, the lpfc_issue_els_plogi()
* routine is invoked to log into the remote port first.
*
* Return code
* 0 - Either the FARP Match Mode not supported or successfully processed
**/
static int static int
lpfc_els_rcv_farp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, lpfc_els_rcv_farp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *ndlp) struct lpfc_nodelist *ndlp)
...@@ -3744,6 +4739,20 @@ lpfc_els_rcv_farp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ...@@ -3744,6 +4739,20 @@ lpfc_els_rcv_farp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
return 0; return 0;
} }
/**
* lpfc_els_rcv_farpr: Process an unsolicited farp response iocb.
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
*
* This routine processes Fibre Channel Address Resolution Protocol
* Response (FARPR) IOCB received as an ELS unsolicited event. It simply
* invokes the lpfc_els_rsp_acc() routine to the remote node to accept
* the FARP response request.
*
* Return code
* 0 - Successfully processed FARPR IOCB (currently always return 0)
**/
static int static int
lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *ndlp) struct lpfc_nodelist *ndlp)
...@@ -3768,6 +4777,25 @@ lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ...@@ -3768,6 +4777,25 @@ lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
return 0; return 0;
} }
/**
* lpfc_els_rcv_fan: Process an unsolicited fan iocb command.
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @fan_ndlp: pointer to a node-list data structure.
*
* This routine processes a Fabric Address Notification (FAN) IOCB
* command received as an ELS unsolicited event. The FAN ELS command will
* only be processed on a physical port (i.e., the @vport represents the
* physical port). The fabric NodeName and PortName from the FAN IOCB are
* compared against those in the phba data structure. If any of those is
* different, the lpfc_initial_flogi() routine is invoked to initialize
* Fabric Login (FLOGI) to the fabric to start the discover over. Otherwise,
* if both of those are identical, the lpfc_issue_fabric_reglogin() routine
* is invoked to register login to the fabric.
*
* Return code
* 0 - Successfully processed fan iocb (currently always return 0).
**/
static int static int
lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *fan_ndlp) struct lpfc_nodelist *fan_ndlp)
...@@ -3797,6 +4825,16 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ...@@ -3797,6 +4825,16 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
return 0; return 0;
} }
/**
* lpfc_els_timeout: Handler funciton to the els timer.
* @ptr: holder for the timer function associated data.
*
* This routine is invoked by the ELS timer after timeout. It posts the ELS
* timer timeout event by setting the WORKER_ELS_TMO bit to the work port
* event bitmap and then invokes the lpfc_worker_wake_up() routine to wake
* up the worker thread. It is for the worker thread to invoke the routine
* lpfc_els_timeout_handler() to work on the posted event WORKER_ELS_TMO.
**/
void void
lpfc_els_timeout(unsigned long ptr) lpfc_els_timeout(unsigned long ptr)
{ {
...@@ -3816,6 +4854,15 @@ lpfc_els_timeout(unsigned long ptr) ...@@ -3816,6 +4854,15 @@ lpfc_els_timeout(unsigned long ptr)
return; return;
} }
/**
* lpfc_els_timeout_handler: Process an els timeout event.
* @vport: pointer to a virtual N_Port data structure.
*
* This routine is the actual handler function that processes an ELS timeout
* event. It walks the ELS ring to get and abort all the IOCBs (except the
* ABORT/CLOSE/FARP/FARPR/FDISC), which are associated with the @vport by
* invoking the lpfc_sli_issue_abort_iotag() routine.
**/
void void
lpfc_els_timeout_handler(struct lpfc_vport *vport) lpfc_els_timeout_handler(struct lpfc_vport *vport)
{ {
...@@ -3886,6 +4933,26 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport) ...@@ -3886,6 +4933,26 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport)
mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout); mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout);
} }
/**
* lpfc_els_flush_cmd: Clean up the outstanding els commands to a vport.
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine is used to clean up all the outstanding ELS commands on a
* @vport. It first aborts the @vport by invoking lpfc_fabric_abort_vport()
* routine. After that, it walks the ELS transmit queue to remove all the
* IOCBs with the @vport other than the QUE_RING and ABORT/CLOSE IOCBs. For
* the IOCBs with a non-NULL completion callback function, the callback
* function will be invoked with the status set to IOSTAT_LOCAL_REJECT and
* un.ulpWord[4] set to IOERR_SLI_ABORTED. For IOCBs with a NULL completion
* callback function, the IOCB will simply be released. Finally, it walks
* the ELS transmit completion queue to issue an abort IOCB to any transmit
* completion queue IOCB that is associated with the @vport and is not
* an IOCB from libdfc (i.e., the management plane IOCBs that are not
* part of the discovery state machine) out to HBA by invoking the
* lpfc_sli_issue_abort_iotag() routine. Note that this function issues the
* abort IOCB to any transmit completion queueed IOCB, it does not guarantee
* the IOCBs are aborted when this function returns.
**/
void void
lpfc_els_flush_cmd(struct lpfc_vport *vport) lpfc_els_flush_cmd(struct lpfc_vport *vport)
{ {
...@@ -3948,6 +5015,23 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) ...@@ -3948,6 +5015,23 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
return; return;
} }
/**
* lpfc_els_flush_all_cmd: Clean up all the outstanding els commands to a HBA.
* @phba: pointer to lpfc hba data structure.
*
* This routine is used to clean up all the outstanding ELS commands on a
* @phba. It first aborts the @phba by invoking the lpfc_fabric_abort_hba()
* routine. After that, it walks the ELS transmit queue to remove all the
* IOCBs to the @phba other than the QUE_RING and ABORT/CLOSE IOCBs. For
* the IOCBs with the completion callback function associated, the callback
* function will be invoked with the status set to IOSTAT_LOCAL_REJECT and
* un.ulpWord[4] set to IOERR_SLI_ABORTED. For IOCBs without the completion
* callback function associated, the IOCB will simply be released. Finally,
* it walks the ELS transmit completion queue to issue an abort IOCB to any
* transmit completion queue IOCB that is not an IOCB from libdfc (i.e., the
* management plane IOCBs that are not part of the discovery state machine)
* out to HBA by invoking the lpfc_sli_issue_abort_iotag() routine.
**/
void void
lpfc_els_flush_all_cmd(struct lpfc_hba *phba) lpfc_els_flush_all_cmd(struct lpfc_hba *phba)
{ {
...@@ -3992,6 +5076,20 @@ lpfc_els_flush_all_cmd(struct lpfc_hba *phba) ...@@ -3992,6 +5076,20 @@ lpfc_els_flush_all_cmd(struct lpfc_hba *phba)
return; return;
} }
/**
* lpfc_els_unsol_buffer: Process an unsolicited event data buffer.
* @phba: pointer to lpfc hba data structure.
* @pring: pointer to a SLI ring.
* @vport: pointer to a host virtual N_Port data structure.
* @elsiocb: pointer to lpfc els command iocb data structure.
*
* This routine is used for processing the IOCB associated with a unsolicited
* event. It first determines whether there is an existing ndlp that matches
* the DID from the unsolicited IOCB. If not, it will create a new one with
* the DID from the unsolicited IOCB. The ELS command from the unsolicited
* IOCB is then used to invoke the proper routine and to set up proper state
* of the discovery state machine.
**/
static void static void
lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_vport *vport, struct lpfc_iocbq *elsiocb) struct lpfc_vport *vport, struct lpfc_iocbq *elsiocb)
...@@ -4282,6 +5380,19 @@ dropit: ...@@ -4282,6 +5380,19 @@ dropit:
phba->fc_stat.elsRcvDrop++; phba->fc_stat.elsRcvDrop++;
} }
/**
* lpfc_find_vport_by_vpid: Find a vport on a HBA through vport identifier.
* @phba: pointer to lpfc hba data structure.
* @vpi: host virtual N_Port identifier.
*
* This routine finds a vport on a HBA (referred by @phba) through a
* @vpi. The function walks the HBA's vport list and returns the address
* of the vport with the matching @vpi.
*
* Return code
* NULL - No vport with the matching @vpi found
* Otherwise - Address to the vport with the matching @vpi.
**/
static struct lpfc_vport * static struct lpfc_vport *
lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi) lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi)
{ {
...@@ -4299,6 +5410,18 @@ lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi) ...@@ -4299,6 +5410,18 @@ lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi)
return NULL; return NULL;
} }
/**
* lpfc_els_unsol_event: Process an unsolicited event from an els sli ring.
* @phba: pointer to lpfc hba data structure.
* @pring: pointer to a SLI ring.
* @elsiocb: pointer to lpfc els iocb data structure.
*
* This routine is used to process an unsolicited event received from a SLI
* (Service Level Interface) ring. The actual processing of the data buffer
* associated with the unsolicited event is done by invoking the routine
* lpfc_els_unsol_buffer() after properly set up the iocb buffer from the
* SLI ring on which the unsolicited event was received.
**/
void void
lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *elsiocb) struct lpfc_iocbq *elsiocb)
...@@ -4376,6 +5499,19 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -4376,6 +5499,19 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
} }
} }
/**
* lpfc_do_scr_ns_plogi: Issue a plogi to the name server for scr.
* @phba: pointer to lpfc hba data structure.
* @vport: pointer to a virtual N_Port data structure.
*
* This routine issues a Port Login (PLOGI) to the Name Server with
* State Change Request (SCR) for a @vport. This routine will create an
* ndlp for the Name Server associated to the @vport if such node does
* not already exist. The PLOGI to Name Server is issued by invoking the
* lpfc_issue_els_plogi() routine. If Fabric-Device Management Interface
* (FDMI) is configured to the @vport, a FDMI node will be created and
* the PLOGI to FDMI is issued by invoking lpfc_issue_els_plogi() routine.
**/
void void
lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport) lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
{ {
...@@ -4434,6 +5570,18 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport) ...@@ -4434,6 +5570,18 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
return; return;
} }
/**
* lpfc_cmpl_reg_new_vport: Completion callback function to register new vport.
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
* This routine is the completion callback function to register new vport
* mailbox command. If the new vport mailbox command completes successfully,
* the fabric registration login shall be performed on physical port (the
* new vport created is actually a physical port, with VPI 0) or the port
* login to Name Server for State Change Request (SCR) will be performed
* on virtual port (real virtual port, with VPI greater than 0).
**/
static void static void
lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{ {
...@@ -4491,6 +5639,15 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -4491,6 +5639,15 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
return; return;
} }
/**
* lpfc_register_new_vport: Register a new vport with a HBA.
* @phba: pointer to lpfc hba data structure.
* @vport: pointer to a host virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
*
* This routine registers the @vport as a new virtual port with a HBA.
* It is done through a registering vpi mailbox command.
**/
static void static void
lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport, lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp) struct lpfc_nodelist *ndlp)
...@@ -4531,6 +5688,26 @@ mbox_err_exit: ...@@ -4531,6 +5688,26 @@ mbox_err_exit:
return; return;
} }
/**
* lpfc_cmpl_els_fdisc: Completion function for fdisc iocb command.
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
*
* This routine is the completion callback function to a Fabric Discover
* (FDISC) ELS command. Since all the FDISC ELS commands are issued
* single threaded, each FDISC completion callback function will reset
* the discovery timer for all vports such that the timers will not get
* unnecessary timeout. The function checks the FDISC IOCB status. If error
* detected, the vport will be set to FC_VPORT_FAILED state. Otherwise,the
* vport will set to FC_VPORT_ACTIVE state. It then checks whether the DID
* assigned to the vport has been changed with the completion of the FDISC
* command. If so, both RPI (Remote Port Index) and VPI (Virtual Port Index)
* are unregistered from the HBA, and then the lpfc_register_new_vport()
* routine is invoked to register new vport with the HBA. Otherwise, the
* lpfc_do_scr_ns_plogi() routine is invoked to issue a PLOGI to the Name
* Server for State Change Request (SCR).
**/
static void static void
lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb) struct lpfc_iocbq *rspiocb)
...@@ -4617,6 +5794,26 @@ out: ...@@ -4617,6 +5794,26 @@ out:
lpfc_els_free_iocb(phba, cmdiocb); lpfc_els_free_iocb(phba, cmdiocb);
} }
/**
* lpfc_issue_els_fdisc: Issue a fdisc iocb command.
* @vport: pointer to a virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
* @retry: number of retries to the command IOCB.
*
* This routine prepares and issues a Fabric Discover (FDISC) IOCB to
* a remote node (@ndlp) off a @vport. It uses the lpfc_issue_fabric_iocb()
* routine to issue the IOCB, which makes sure only one outstanding fabric
* IOCB will be sent off HBA at any given time.
*
* Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
* will be incremented by 1 for holding the ndlp and the reference to ndlp
* will be stored into the context1 field of the IOCB for the completion
* callback function to the FDISC ELS command.
*
* Return code
* 0 - Successfully issued fdisc iocb command
* 1 - Failed to issue fdisc iocb command
**/
static int static int
lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
uint8_t retry) uint8_t retry)
...@@ -4691,6 +5888,20 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -4691,6 +5888,20 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
return 0; return 0;
} }
/**
* lpfc_cmpl_els_npiv_logo: Completion function with vport logo.
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
*
* This routine is the completion callback function to the issuing of a LOGO
* ELS command off a vport. It frees the command IOCB and then decrement the
* reference count held on ndlp for this completion function, indicating that
* the reference to the ndlp is no long needed. Note that the
* lpfc_els_free_iocb() routine decrements the ndlp reference held for this
* callback function and an additional explicit ndlp reference decrementation
* will trigger the actual release of the ndlp.
**/
static void static void
lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb) struct lpfc_iocbq *rspiocb)
...@@ -4712,6 +5923,22 @@ lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -4712,6 +5923,22 @@ lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_nlp_put(ndlp); lpfc_nlp_put(ndlp);
} }
/**
* lpfc_issue_els_npiv_logo: Issue a logo off a vport.
* @vport: pointer to a virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
*
* This routine issues a LOGO ELS command to an @ndlp off a @vport.
*
* Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
* will be incremented by 1 for holding the ndlp and the reference to ndlp
* will be stored into the context1 field of the IOCB for the completion
* callback function to the LOGO ELS command.
*
* Return codes
* 0 - Successfully issued logo off the @vport
* 1 - Failed to issue logo off the @vport
**/
int int
lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
{ {
...@@ -4757,6 +5984,17 @@ lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ...@@ -4757,6 +5984,17 @@ lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
return 0; return 0;
} }
/**
* lpfc_fabric_block_timeout: Handler function to the fabric block timer.
* @ptr: holder for the timer function associated data.
*
* This routine is invoked by the fabric iocb block timer after
* timeout. It posts the fabric iocb block timeout event by setting the
* WORKER_FABRIC_BLOCK_TMO bit to work port event bitmap and then invokes
* lpfc_worker_wake_up() routine to wake up the worker thread. It is for
* the worker thread to invoke the lpfc_unblock_fabric_iocbs() on the
* posted event WORKER_FABRIC_BLOCK_TMO.
**/
void void
lpfc_fabric_block_timeout(unsigned long ptr) lpfc_fabric_block_timeout(unsigned long ptr)
{ {
...@@ -4775,6 +6013,16 @@ lpfc_fabric_block_timeout(unsigned long ptr) ...@@ -4775,6 +6013,16 @@ lpfc_fabric_block_timeout(unsigned long ptr)
return; return;
} }
/**
* lpfc_resume_fabric_iocbs: Issue a fabric iocb from driver internal list.
* @phba: pointer to lpfc hba data structure.
*
* This routine issues one fabric iocb from the driver internal list to
* the HBA. It first checks whether it's ready to issue one fabric iocb to
* the HBA (whether there is no outstanding fabric iocb). If so, it shall
* remove one pending fabric iocb from the driver internal list and invokes
* lpfc_sli_issue_iocb() routine to send the fabric iocb to the HBA.
**/
static void static void
lpfc_resume_fabric_iocbs(struct lpfc_hba *phba) lpfc_resume_fabric_iocbs(struct lpfc_hba *phba)
{ {
...@@ -4824,6 +6072,15 @@ repeat: ...@@ -4824,6 +6072,15 @@ repeat:
return; return;
} }
/**
* lpfc_unblock_fabric_iocbs: Unblock issuing fabric iocb command.
* @phba: pointer to lpfc hba data structure.
*
* This routine unblocks the issuing fabric iocb command. The function
* will clear the fabric iocb block bit and then invoke the routine
* lpfc_resume_fabric_iocbs() to issue one of the pending fabric iocb
* from the driver internal fabric iocb list.
**/
void void
lpfc_unblock_fabric_iocbs(struct lpfc_hba *phba) lpfc_unblock_fabric_iocbs(struct lpfc_hba *phba)
{ {
...@@ -4833,6 +6090,15 @@ lpfc_unblock_fabric_iocbs(struct lpfc_hba *phba) ...@@ -4833,6 +6090,15 @@ lpfc_unblock_fabric_iocbs(struct lpfc_hba *phba)
return; return;
} }
/**
* lpfc_block_fabric_iocbs: Block issuing fabric iocb command.
* @phba: pointer to lpfc hba data structure.
*
* This routine blocks the issuing fabric iocb for a specified amount of
* time (currently 100 ms). This is done by set the fabric iocb block bit
* and set up a timeout timer for 100ms. When the block bit is set, no more
* fabric iocb will be issued out of the HBA.
**/
static void static void
lpfc_block_fabric_iocbs(struct lpfc_hba *phba) lpfc_block_fabric_iocbs(struct lpfc_hba *phba)
{ {
...@@ -4846,6 +6112,19 @@ lpfc_block_fabric_iocbs(struct lpfc_hba *phba) ...@@ -4846,6 +6112,19 @@ lpfc_block_fabric_iocbs(struct lpfc_hba *phba)
return; return;
} }
/**
* lpfc_cmpl_fabric_iocb: Completion callback function for fabric iocb.
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
*
* This routine is the callback function that is put to the fabric iocb's
* callback function pointer (iocb->iocb_cmpl). The original iocb's callback
* function pointer has been stored in iocb->fabric_iocb_cmpl. This callback
* function first restores and invokes the original iocb's callback function
* and then invokes the lpfc_resume_fabric_iocbs() routine to issue the next
* fabric bound iocb from the driver internal fabric iocb list onto the wire.
**/
static void static void
lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb) struct lpfc_iocbq *rspiocb)
...@@ -4892,6 +6171,30 @@ lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -4892,6 +6171,30 @@ lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
} }
} }
/**
* lpfc_issue_fabric_iocb: Issue a fabric iocb command.
* @phba: pointer to lpfc hba data structure.
* @iocb: pointer to lpfc command iocb data structure.
*
* This routine is used as the top-level API for issuing a fabric iocb command
* such as FLOGI and FDISC. To accommodate certain switch fabric, this driver
* function makes sure that only one fabric bound iocb will be outstanding at
* any given time. As such, this function will first check to see whether there
* is already an outstanding fabric iocb on the wire. If so, it will put the
* newly issued iocb onto the driver internal fabric iocb list, waiting to be
* issued later. Otherwise, it will issue the iocb on the wire and update the
* fabric iocb count it indicate that there is one fabric iocb on the wire.
*
* Note, this implementation has a potential sending out fabric IOCBs out of
* order. The problem is caused by the construction of the "ready" boolen does
* not include the condition that the internal fabric IOCB list is empty. As
* such, it is possible a fabric IOCB issued by this routine might be "jump"
* ahead of the fabric IOCBs in the internal list.
*
* Return code
* IOCB_SUCCESS - either fabric iocb put on the list or issued successfully
* IOCB_ERROR - failed to issue fabric iocb
**/
static int static int
lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb) lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb)
{ {
...@@ -4937,7 +6240,17 @@ lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb) ...@@ -4937,7 +6240,17 @@ lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb)
return ret; return ret;
} }
/**
* lpfc_fabric_abort_vport: Abort a vport's iocbs from driver fabric iocb list.
* @vport: pointer to a virtual N_Port data structure.
*
* This routine aborts all the IOCBs associated with a @vport from the
* driver internal fabric IOCB list. The list contains fabric IOCBs to be
* issued to the ELS IOCB ring. This abort function walks the fabric IOCB
* list, removes each IOCB associated with the @vport off the list, set the
* status feild to IOSTAT_LOCAL_REJECT, and invokes the callback function
* associated with the IOCB.
**/
static void lpfc_fabric_abort_vport(struct lpfc_vport *vport) static void lpfc_fabric_abort_vport(struct lpfc_vport *vport)
{ {
LIST_HEAD(completions); LIST_HEAD(completions);
...@@ -4967,6 +6280,17 @@ static void lpfc_fabric_abort_vport(struct lpfc_vport *vport) ...@@ -4967,6 +6280,17 @@ static void lpfc_fabric_abort_vport(struct lpfc_vport *vport)
} }
} }
/**
* lpfc_fabric_abort_nport: Abort a ndlp's iocbs from driver fabric iocb list.
* @ndlp: pointer to a node-list data structure.
*
* This routine aborts all the IOCBs associated with an @ndlp from the
* driver internal fabric IOCB list. The list contains fabric IOCBs to be
* issued to the ELS IOCB ring. This abort function walks the fabric IOCB
* list, removes each IOCB associated with the @ndlp off the list, set the
* status feild to IOSTAT_LOCAL_REJECT, and invokes the callback function
* associated with the IOCB.
**/
void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp) void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp)
{ {
LIST_HEAD(completions); LIST_HEAD(completions);
...@@ -4996,6 +6320,17 @@ void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp) ...@@ -4996,6 +6320,17 @@ void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp)
} }
} }
/**
* lpfc_fabric_abort_hba: Abort all iocbs on driver fabric iocb list.
* @phba: pointer to lpfc hba data structure.
*
* This routine aborts all the IOCBs currently on the driver internal
* fabric IOCB list. The list contains fabric IOCBs to be issued to the ELS
* IOCB ring. This function takes the entire IOCB list off the fabric IOCB
* list, removes IOCBs off the list, set the status feild to
* IOSTAT_LOCAL_REJECT, and invokes the callback function associated with
* the IOCB.
**/
void lpfc_fabric_abort_hba(struct lpfc_hba *phba) void lpfc_fabric_abort_hba(struct lpfc_hba *phba)
{ {
LIST_HEAD(completions); LIST_HEAD(completions);
......
...@@ -52,17 +52,20 @@ static struct scsi_transport_template *lpfc_transport_template = NULL; ...@@ -52,17 +52,20 @@ static struct scsi_transport_template *lpfc_transport_template = NULL;
static struct scsi_transport_template *lpfc_vport_transport_template = NULL; static struct scsi_transport_template *lpfc_vport_transport_template = NULL;
static DEFINE_IDR(lpfc_hba_index); static DEFINE_IDR(lpfc_hba_index);
/************************************************************************/ /**
/* */ * lpfc_config_port_prep: Perform lpfc initialization prior to config port.
/* lpfc_config_port_prep */ * @phba: pointer to lpfc hba data structure.
/* This routine will do LPFC initialization prior to the */ *
/* CONFIG_PORT mailbox command. This will be initialized */ * This routine will do LPFC initialization prior to issuing the CONFIG_PORT
/* as a SLI layer callback routine. */ * mailbox command. It retrieves the revision information from the HBA and
/* This routine returns 0 on success or -ERESTART if it wants */ * collects the Vital Product Data (VPD) about the HBA for preparing the
/* the SLI layer to reset the HBA and try again. Any */ * configuration of the HBA.
/* other return value indicates an error. */ *
/* */ * Return codes:
/************************************************************************/ * 0 - success.
* -ERESTART - requests the SLI layer to reset the HBA and try again.
* Any other value - indicates an error.
**/
int int
lpfc_config_port_prep(struct lpfc_hba *phba) lpfc_config_port_prep(struct lpfc_hba *phba)
{ {
...@@ -214,7 +217,16 @@ out_free_mbox: ...@@ -214,7 +217,16 @@ out_free_mbox:
return 0; return 0;
} }
/* Completion handler for config async event mailbox command. */ /**
* lpfc_config_async_cmpl: Completion handler for config async event mbox cmd.
* @phba: pointer to lpfc hba data structure.
* @pmboxq: pointer to the driver internal queue element for mailbox command.
*
* This is the completion handler for driver's configuring asynchronous event
* mailbox command to the device. If the mailbox command returns successfully,
* it will set internal async event support flag to 1; otherwise, it will
* set internal async event support flag to 0.
**/
static void static void
lpfc_config_async_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq) lpfc_config_async_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
{ {
...@@ -226,16 +238,19 @@ lpfc_config_async_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq) ...@@ -226,16 +238,19 @@ lpfc_config_async_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
return; return;
} }
/************************************************************************/ /**
/* */ * lpfc_config_port_post: Perform lpfc initialization after config port.
/* lpfc_config_port_post */ * @phba: pointer to lpfc hba data structure.
/* This routine will do LPFC initialization after the */ *
/* CONFIG_PORT mailbox command. This will be initialized */ * This routine will do LPFC initialization after the CONFIG_PORT mailbox
/* as a SLI layer callback routine. */ * command call. It performs all internal resource and state setups on the
/* This routine returns 0 on success. Any other return value */ * port: post IOCB buffers, enable appropriate host interrupt attentions,
/* indicates an error. */ * ELS ring timers, etc.
/* */ *
/************************************************************************/ * Return codes
* 0 - success.
* Any other value - error.
**/
int int
lpfc_config_port_post(struct lpfc_hba *phba) lpfc_config_port_post(struct lpfc_hba *phba)
{ {
...@@ -450,16 +465,17 @@ lpfc_config_port_post(struct lpfc_hba *phba) ...@@ -450,16 +465,17 @@ lpfc_config_port_post(struct lpfc_hba *phba)
return (0); return (0);
} }
/************************************************************************/ /**
/* */ * lpfc_hba_down_prep: Perform lpfc uninitialization prior to HBA reset.
/* lpfc_hba_down_prep */ * @phba: pointer to lpfc HBA data structure.
/* This routine will do LPFC uninitialization before the */ *
/* HBA is reset when bringing down the SLI Layer. This will be */ * This routine will do LPFC uninitialization before the HBA is reset when
/* initialized as a SLI layer callback routine. */ * bringing down the SLI Layer.
/* This routine returns 0 on success. Any other return value */ *
/* indicates an error. */ * Return codes
/* */ * 0 - success.
/************************************************************************/ * Any other value - error.
**/
int int
lpfc_hba_down_prep(struct lpfc_hba *phba) lpfc_hba_down_prep(struct lpfc_hba *phba)
{ {
...@@ -481,15 +497,17 @@ lpfc_hba_down_prep(struct lpfc_hba *phba) ...@@ -481,15 +497,17 @@ lpfc_hba_down_prep(struct lpfc_hba *phba)
return 0; return 0;
} }
/************************************************************************/ /**
/* */ * lpfc_hba_down_post: Perform lpfc uninitialization after HBA reset.
/* lpfc_hba_down_post */ * @phba: pointer to lpfc HBA data structure.
/* This routine will do uninitialization after the HBA is reset */ *
/* when bringing down the SLI Layer. */ * This routine will do uninitialization after the HBA is reset when bring
/* This routine returns 0 on success. Any other return value */ * down the SLI Layer.
/* indicates an error. */ *
/* */ * Return codes
/************************************************************************/ * 0 - sucess.
* Any other value - error.
**/
int int
lpfc_hba_down_post(struct lpfc_hba *phba) lpfc_hba_down_post(struct lpfc_hba *phba)
{ {
...@@ -548,7 +566,18 @@ lpfc_hba_down_post(struct lpfc_hba *phba) ...@@ -548,7 +566,18 @@ lpfc_hba_down_post(struct lpfc_hba *phba)
return 0; return 0;
} }
/* HBA heart beat timeout handler */ /**
* lpfc_hb_timeout: The HBA-timer timeout handler.
* @ptr: unsigned long holds the pointer to lpfc hba data structure.
*
* This is the HBA-timer timeout handler registered to the lpfc driver. When
* this timer fires, a HBA timeout event shall be posted to the lpfc driver
* work-port-events bitmap and the worker thread is notified. This timeout
* event will be used by the worker thread to invoke the actual timeout
* handler routine, lpfc_hb_timeout_handler. Any periodical operations will
* be performed in the timeout handler and the HBA timeout event bit shall
* be cleared by the worker thread after it has taken the event bitmap out.
**/
static void static void
lpfc_hb_timeout(unsigned long ptr) lpfc_hb_timeout(unsigned long ptr)
{ {
...@@ -568,6 +597,22 @@ lpfc_hb_timeout(unsigned long ptr) ...@@ -568,6 +597,22 @@ lpfc_hb_timeout(unsigned long ptr)
return; return;
} }
/**
* lpfc_hb_mbox_cmpl: The lpfc heart-beat mailbox command callback function.
* @phba: pointer to lpfc hba data structure.
* @pmboxq: pointer to the driver internal queue element for mailbox command.
*
* This is the callback function to the lpfc heart-beat mailbox command.
* If configured, the lpfc driver issues the heart-beat mailbox command to
* the HBA every LPFC_HB_MBOX_INTERVAL (current 5) seconds. At the time the
* heart-beat mailbox command is issued, the driver shall set up heart-beat
* timeout timer to LPFC_HB_MBOX_TIMEOUT (current 30) seconds and marks
* heart-beat outstanding state. Once the mailbox command comes back and
* no error conditions detected, the heart-beat mailbox command timer is
* reset to LPFC_HB_MBOX_INTERVAL seconds and the heart-beat outstanding
* state is cleared for the next heart-beat. If the timer expired with the
* heart-beat outstanding state set, the driver will put the HBA offline.
**/
static void static void
lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq) lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
{ {
...@@ -586,6 +631,22 @@ lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq) ...@@ -586,6 +631,22 @@ lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
return; return;
} }
/**
* lpfc_hb_timeout_handler: The HBA-timer timeout handler.
* @phba: pointer to lpfc hba data structure.
*
* This is the actual HBA-timer timeout handler to be invoked by the worker
* thread whenever the HBA timer fired and HBA-timeout event posted. This
* handler performs any periodic operations needed for the device. If such
* periodic event has already been attended to either in the interrupt handler
* or by processing slow-ring or fast-ring events within the HBA-timer
* timeout window (LPFC_HB_MBOX_INTERVAL), this handler just simply resets
* the timer for the next timeout period. If lpfc heart-beat mailbox command
* is configured and there is no heart-beat mailbox command outstanding, a
* heart-beat mailbox is issued and timer set properly. Otherwise, if there
* has been a heart-beat mailbox command outstanding, the HBA shall be put
* to offline.
**/
void void
lpfc_hb_timeout_handler(struct lpfc_hba *phba) lpfc_hb_timeout_handler(struct lpfc_hba *phba)
{ {
...@@ -684,6 +745,13 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba) ...@@ -684,6 +745,13 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba)
} }
} }
/**
* lpfc_offline_eratt: Bring lpfc offline on hardware error attention.
* @phba: pointer to lpfc hba data structure.
*
* This routine is called to bring the HBA offline when HBA hardware error
* other than Port Error 6 has been detected.
**/
static void static void
lpfc_offline_eratt(struct lpfc_hba *phba) lpfc_offline_eratt(struct lpfc_hba *phba)
{ {
...@@ -704,14 +772,16 @@ lpfc_offline_eratt(struct lpfc_hba *phba) ...@@ -704,14 +772,16 @@ lpfc_offline_eratt(struct lpfc_hba *phba)
return; return;
} }
/************************************************************************/ /**
/* */ * lpfc_handle_eratt: The HBA hardware error handler.
/* lpfc_handle_eratt */ * @phba: pointer to lpfc hba data structure.
/* This routine will handle processing a Host Attention */ *
/* Error Status event. This will be initialized */ * This routine is invoked to handle the following HBA hardware error
/* as a SLI layer callback routine. */ * conditions:
/* */ * 1 - HBA error attention interrupt
/************************************************************************/ * 2 - DMA ring index out of range
* 3 - Mailbox command came back as unknown
**/
void void
lpfc_handle_eratt(struct lpfc_hba *phba) lpfc_handle_eratt(struct lpfc_hba *phba)
{ {
...@@ -810,14 +880,13 @@ lpfc_handle_eratt(struct lpfc_hba *phba) ...@@ -810,14 +880,13 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
} }
} }
/************************************************************************/ /**
/* */ * lpfc_handle_latt: The HBA link event handler.
/* lpfc_handle_latt */ * @phba: pointer to lpfc hba data structure.
/* This routine will handle processing a Host Attention */ *
/* Link Status event. This will be initialized */ * This routine is invoked from the worker thread to handle a HBA host
/* as a SLI layer callback routine. */ * attention link event.
/* */ **/
/************************************************************************/
void void
lpfc_handle_latt(struct lpfc_hba *phba) lpfc_handle_latt(struct lpfc_hba *phba)
{ {
...@@ -898,12 +967,20 @@ lpfc_handle_latt_err_exit: ...@@ -898,12 +967,20 @@ lpfc_handle_latt_err_exit:
return; return;
} }
/************************************************************************/ /**
/* */ * lpfc_parse_vpd: Parse VPD (Vital Product Data).
/* lpfc_parse_vpd */ * @phba: pointer to lpfc hba data structure.
/* This routine will parse the VPD data */ * @vpd: pointer to the vital product data.
/* */ * @len: length of the vital product data in bytes.
/************************************************************************/ *
* This routine parses the Vital Product Data (VPD). The VPD is treated as
* an array of characters. In this routine, the ModelName, ProgramType, and
* ModelDesc, etc. fields of the phba data structure will be populated.
*
* Return codes
* 0 - pointer to the VPD passed in is NULL
* 1 - success
**/
static int static int
lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len) lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len)
{ {
...@@ -1040,6 +1117,18 @@ lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len) ...@@ -1040,6 +1117,18 @@ lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len)
return(1); return(1);
} }
/**
* lpfc_get_hba_model_desc: Retrieve HBA device model name and description.
* @phba: pointer to lpfc hba data structure.
* @mdp: pointer to the data structure to hold the derived model name.
* @descp: pointer to the data structure to hold the derived description.
*
* This routine retrieves HBA's description based on its registered PCI device
* ID. The @descp passed into this function points to an array of 256 chars. It
* shall be returned with the model name, maximum speed, and the host bus type.
* The @mdp passed into this function points to an array of 80 chars. When the
* function returns, the @mdp will be filled with the model name.
**/
static void static void
lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp) lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
{ {
...@@ -1190,14 +1279,18 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp) ...@@ -1190,14 +1279,18 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
m.name, m.max_speed, m.bus); m.name, m.max_speed, m.bus);
} }
/**************************************************/ /**
/* lpfc_post_buffer */ * lpfc_post_buffer: Post IOCB(s) with DMA buffer descriptor(s) to a IOCB ring.
/* */ * @phba: pointer to lpfc hba data structure.
/* This routine will post count buffers to the */ * @pring: pointer to a IOCB ring.
/* ring with the QUE_RING_BUF_CN command. This */ * @cnt: the number of IOCBs to be posted to the IOCB ring.
/* allows 3 buffers / command to be posted. */ *
/* Returns the number of buffers NOT posted. */ * This routine posts a given number of IOCBs with the associated DMA buffer
/**************************************************/ * descriptors specified by the cnt argument to the given IOCB ring.
*
* Return codes
* The number of IOCBs NOT able to be posted to the IOCB ring.
**/
int int
lpfc_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt) lpfc_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt)
{ {
...@@ -1287,12 +1380,17 @@ lpfc_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt) ...@@ -1287,12 +1380,17 @@ lpfc_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt)
return 0; return 0;
} }
/************************************************************************/ /**
/* */ * lpfc_post_rcv_buf: Post the initial receive IOCB buffers to ELS ring.
/* lpfc_post_rcv_buf */ * @phba: pointer to lpfc hba data structure.
/* This routine post initial rcv buffers to the configured rings */ *
/* */ * This routine posts initial receive IOCB buffers to the ELS ring. The
/************************************************************************/ * current number of initial IOCB buffers specified by LPFC_BUF_RING0 is
* set to 64 IOCBs.
*
* Return codes
* 0 - success (currently always success)
**/
static int static int
lpfc_post_rcv_buf(struct lpfc_hba *phba) lpfc_post_rcv_buf(struct lpfc_hba *phba)
{ {
...@@ -1307,11 +1405,13 @@ lpfc_post_rcv_buf(struct lpfc_hba *phba) ...@@ -1307,11 +1405,13 @@ lpfc_post_rcv_buf(struct lpfc_hba *phba)
#define S(N,V) (((V)<<(N))|((V)>>(32-(N)))) #define S(N,V) (((V)<<(N))|((V)>>(32-(N))))
/************************************************************************/ /**
/* */ * lpfc_sha_init: Set up initial array of hash table entries.
/* lpfc_sha_init */ * @HashResultPointer: pointer to an array as hash table.
/* */ *
/************************************************************************/ * This routine sets up the initial values to the array of hash table entries
* for the LC HBAs.
**/
static void static void
lpfc_sha_init(uint32_t * HashResultPointer) lpfc_sha_init(uint32_t * HashResultPointer)
{ {
...@@ -1322,11 +1422,16 @@ lpfc_sha_init(uint32_t * HashResultPointer) ...@@ -1322,11 +1422,16 @@ lpfc_sha_init(uint32_t * HashResultPointer)
HashResultPointer[4] = 0xC3D2E1F0; HashResultPointer[4] = 0xC3D2E1F0;
} }
/************************************************************************/ /**
/* */ * lpfc_sha_iterate: Iterate initial hash table with the working hash table.
/* lpfc_sha_iterate */ * @HashResultPointer: pointer to an initial/result hash table.
/* */ * @HashWorkingPointer: pointer to an working hash table.
/************************************************************************/ *
* This routine iterates an initial hash table pointed by @HashResultPointer
* with the values from the working hash table pointeed by @HashWorkingPointer.
* The results are putting back to the initial hash table, returned through
* the @HashResultPointer as the result hash table.
**/
static void static void
lpfc_sha_iterate(uint32_t * HashResultPointer, uint32_t * HashWorkingPointer) lpfc_sha_iterate(uint32_t * HashResultPointer, uint32_t * HashWorkingPointer)
{ {
...@@ -1374,22 +1479,29 @@ lpfc_sha_iterate(uint32_t * HashResultPointer, uint32_t * HashWorkingPointer) ...@@ -1374,22 +1479,29 @@ lpfc_sha_iterate(uint32_t * HashResultPointer, uint32_t * HashWorkingPointer)
} }
/************************************************************************/ /**
/* */ * lpfc_challenge_key: Create challenge key based on WWPN of the HBA.
/* lpfc_challenge_key */ * @RandomChallenge: pointer to the entry of host challenge random number array.
/* */ * @HashWorking: pointer to the entry of the working hash array.
/************************************************************************/ *
* This routine calculates the working hash array referred by @HashWorking
* from the challenge random numbers associated with the host, referred by
* @RandomChallenge. The result is put into the entry of the working hash
* array and returned by reference through @HashWorking.
**/
static void static void
lpfc_challenge_key(uint32_t * RandomChallenge, uint32_t * HashWorking) lpfc_challenge_key(uint32_t * RandomChallenge, uint32_t * HashWorking)
{ {
*HashWorking = (*RandomChallenge ^ *HashWorking); *HashWorking = (*RandomChallenge ^ *HashWorking);
} }
/************************************************************************/ /**
/* */ * lpfc_hba_init: Perform special handling for LC HBA initialization.
/* lpfc_hba_init */ * @phba: pointer to lpfc hba data structure.
/* */ * @hbainit: pointer to an array of unsigned 32-bit integers.
/************************************************************************/ *
* This routine performs the special handling for LC HBA initialization.
**/
void void
lpfc_hba_init(struct lpfc_hba *phba, uint32_t *hbainit) lpfc_hba_init(struct lpfc_hba *phba, uint32_t *hbainit)
{ {
...@@ -1412,6 +1524,15 @@ lpfc_hba_init(struct lpfc_hba *phba, uint32_t *hbainit) ...@@ -1412,6 +1524,15 @@ lpfc_hba_init(struct lpfc_hba *phba, uint32_t *hbainit)
kfree(HashWorking); kfree(HashWorking);
} }
/**
* lpfc_cleanup: Performs vport cleanups before deleting a vport.
* @vport: pointer to a virtual N_Port data structure.
*
* This routine performs the necessary cleanups before deleting the @vport.
* It invokes the discovery state machine to perform necessary state
* transitions and to release the ndlps associated with the @vport. Note,
* the physical port is treated as @vport 0.
**/
void void
lpfc_cleanup(struct lpfc_vport *vport) lpfc_cleanup(struct lpfc_vport *vport)
{ {
...@@ -1498,6 +1619,14 @@ lpfc_cleanup(struct lpfc_vport *vport) ...@@ -1498,6 +1619,14 @@ lpfc_cleanup(struct lpfc_vport *vport)
return; return;
} }
/**
* lpfc_stop_vport_timers: Stop all the timers associated with a vport.
* @vport: pointer to a virtual N_Port data structure.
*
* This routine stops all the timers associated with a @vport. This function
* is invoked before disabling or deleting a @vport. Note that the physical
* port is treated as @vport 0.
**/
void void
lpfc_stop_vport_timers(struct lpfc_vport *vport) lpfc_stop_vport_timers(struct lpfc_vport *vport)
{ {
...@@ -1507,6 +1636,13 @@ lpfc_stop_vport_timers(struct lpfc_vport *vport) ...@@ -1507,6 +1636,13 @@ lpfc_stop_vport_timers(struct lpfc_vport *vport)
return; return;
} }
/**
* lpfc_stop_phba_timers: Stop all the timers associated with an HBA.
* @phba: pointer to lpfc hba data structure.
*
* This routine stops all the timers associated with a HBA. This function is
* invoked before either putting a HBA offline or unloading the driver.
**/
static void static void
lpfc_stop_phba_timers(struct lpfc_hba *phba) lpfc_stop_phba_timers(struct lpfc_hba *phba)
{ {
...@@ -1519,6 +1655,16 @@ lpfc_stop_phba_timers(struct lpfc_hba *phba) ...@@ -1519,6 +1655,16 @@ lpfc_stop_phba_timers(struct lpfc_hba *phba)
return; return;
} }
/**
* lpfc_block_mgmt_io: Mark a HBA's management interface as blocked.
* @phba: pointer to lpfc hba data structure.
*
* This routine marks a HBA's management interface as blocked. Once the HBA's
* management interface is marked as blocked, all the user space access to
* the HBA, whether they are from sysfs interface or libdfc interface will
* all be blocked. The HBA is set to block the management interface when the
* driver prepares the HBA interface for online or offline.
**/
static void static void
lpfc_block_mgmt_io(struct lpfc_hba * phba) lpfc_block_mgmt_io(struct lpfc_hba * phba)
{ {
...@@ -1529,6 +1675,18 @@ lpfc_block_mgmt_io(struct lpfc_hba * phba) ...@@ -1529,6 +1675,18 @@ lpfc_block_mgmt_io(struct lpfc_hba * phba)
spin_unlock_irqrestore(&phba->hbalock, iflag); spin_unlock_irqrestore(&phba->hbalock, iflag);
} }
/**
* lpfc_online: Initialize and bring a HBA online.
* @phba: pointer to lpfc hba data structure.
*
* This routine initializes the HBA and brings a HBA online. During this
* process, the management interface is blocked to prevent user space access
* to the HBA interfering with the driver initialization.
*
* Return codes
* 0 - successful
* 1 - failed
**/
int int
lpfc_online(struct lpfc_hba *phba) lpfc_online(struct lpfc_hba *phba)
{ {
...@@ -1574,6 +1732,17 @@ lpfc_online(struct lpfc_hba *phba) ...@@ -1574,6 +1732,17 @@ lpfc_online(struct lpfc_hba *phba)
return 0; return 0;
} }
/**
* lpfc_unblock_mgmt_io: Mark a HBA's management interface to be not blocked.
* @phba: pointer to lpfc hba data structure.
*
* This routine marks a HBA's management interface as not blocked. Once the
* HBA's management interface is marked as not blocked, all the user space
* access to the HBA, whether they are from sysfs interface or libdfc
* interface will be allowed. The HBA is set to block the management interface
* when the driver prepares the HBA interface for online or offline and then
* set to unblock the management interface afterwards.
**/
void void
lpfc_unblock_mgmt_io(struct lpfc_hba * phba) lpfc_unblock_mgmt_io(struct lpfc_hba * phba)
{ {
...@@ -1584,6 +1753,14 @@ lpfc_unblock_mgmt_io(struct lpfc_hba * phba) ...@@ -1584,6 +1753,14 @@ lpfc_unblock_mgmt_io(struct lpfc_hba * phba)
spin_unlock_irqrestore(&phba->hbalock, iflag); spin_unlock_irqrestore(&phba->hbalock, iflag);
} }
/**
* lpfc_offline_prep: Prepare a HBA to be brought offline.
* @phba: pointer to lpfc hba data structure.
*
* This routine is invoked to prepare a HBA to be brought offline. It performs
* unregistration login to all the nodes on all vports and flushes the mailbox
* queue to make it ready to be brought offline.
**/
void void
lpfc_offline_prep(struct lpfc_hba * phba) lpfc_offline_prep(struct lpfc_hba * phba)
{ {
...@@ -1633,6 +1810,14 @@ lpfc_offline_prep(struct lpfc_hba * phba) ...@@ -1633,6 +1810,14 @@ lpfc_offline_prep(struct lpfc_hba * phba)
lpfc_sli_flush_mbox_queue(phba); lpfc_sli_flush_mbox_queue(phba);
} }
/**
* lpfc_offline: Bring a HBA offline.
* @phba: pointer to lpfc hba data structure.
*
* This routine actually brings a HBA offline. It stops all the timers
* associated with the HBA, brings down the SLI layer, and eventually
* marks the HBA as in offline state for the upper layer protocol.
**/
void void
lpfc_offline(struct lpfc_hba *phba) lpfc_offline(struct lpfc_hba *phba)
{ {
...@@ -1670,12 +1855,17 @@ lpfc_offline(struct lpfc_hba *phba) ...@@ -1670,12 +1855,17 @@ lpfc_offline(struct lpfc_hba *phba)
lpfc_destroy_vport_work_array(phba, vports); lpfc_destroy_vport_work_array(phba, vports);
} }
/****************************************************************************** /**
* Function name: lpfc_scsi_free * lpfc_scsi_free: Free all the SCSI buffers and IOCBs from driver lists.
* * @phba: pointer to lpfc hba data structure.
* Description: Called from lpfc_pci_remove_one free internal driver resources *
* * This routine is to free all the SCSI buffers and IOCBs from the driver
******************************************************************************/ * list back to kernel. It is called from lpfc_pci_remove_one to free
* the internal resources before the device is removed from the system.
*
* Return codes
* 0 - successful (for now, it always returns 0)
**/
static int static int
lpfc_scsi_free(struct lpfc_hba *phba) lpfc_scsi_free(struct lpfc_hba *phba)
{ {
...@@ -1704,6 +1894,22 @@ lpfc_scsi_free(struct lpfc_hba *phba) ...@@ -1704,6 +1894,22 @@ lpfc_scsi_free(struct lpfc_hba *phba)
return 0; return 0;
} }
/**
* lpfc_create_port: Create an FC port.
* @phba: pointer to lpfc hba data structure.
* @instance: a unique integer ID to this FC port.
* @dev: pointer to the device data structure.
*
* This routine creates a FC port for the upper layer protocol. The FC port
* can be created on top of either a physical port or a virtual port provided
* by the HBA. This routine also allocates a SCSI host data structure (shost)
* and associates the FC port created before adding the shost into the SCSI
* layer.
*
* Return codes
* @vport - pointer to the virtual N_Port data structure.
* NULL - port create failed.
**/
struct lpfc_vport * struct lpfc_vport *
lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev) lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)
{ {
...@@ -1777,6 +1983,13 @@ out: ...@@ -1777,6 +1983,13 @@ out:
return NULL; return NULL;
} }
/**
* destroy_port: Destroy an FC port.
* @vport: pointer to an lpfc virtual N_Port data structure.
*
* This routine destroys a FC port from the upper layer protocol. All the
* resources associated with the port are released.
**/
void void
destroy_port(struct lpfc_vport *vport) destroy_port(struct lpfc_vport *vport)
{ {
...@@ -1797,6 +2010,16 @@ destroy_port(struct lpfc_vport *vport) ...@@ -1797,6 +2010,16 @@ destroy_port(struct lpfc_vport *vport)
return; return;
} }
/**
* lpfc_get_instance: Get a unique integer ID.
*
* This routine allocates a unique integer ID from lpfc_hba_index pool. It
* uses the kernel idr facility to perform the task.
*
* Return codes:
* instance - a unique integer ID allocated as the new instance.
* -1 - lpfc get instance failed.
**/
int int
lpfc_get_instance(void) lpfc_get_instance(void)
{ {
...@@ -1810,11 +2033,21 @@ lpfc_get_instance(void) ...@@ -1810,11 +2033,21 @@ lpfc_get_instance(void)
return instance; return instance;
} }
/* /**
* Note: there is no scan_start function as adapter initialization * lpfc_scan_finished: method for SCSI layer to detect whether scan is done.
* will have asynchronously kicked off the link initialization. * @shost: pointer to SCSI host data structure.
*/ * @time: elapsed time of the scan in jiffies.
*
* This routine is called by the SCSI layer with a SCSI host to determine
* whether the scan host is finished.
*
* Note: there is no scan_start function as adapter initialization will have
* asynchronously kicked off the link initialization.
*
* Return codes
* 0 - SCSI host scan is not over yet.
* 1 - SCSI host scan is over.
**/
int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time) int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time)
{ {
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
...@@ -1858,6 +2091,13 @@ finished: ...@@ -1858,6 +2091,13 @@ finished:
return stat; return stat;
} }
/**
* lpfc_host_attrib_init: Initialize SCSI host attributes on a FC port.
* @shost: pointer to SCSI host data structure.
*
* This routine initializes a given SCSI host attributes on a FC port. The
* SCSI host can be either on top of a physical port or a virtual port.
**/
void lpfc_host_attrib_init(struct Scsi_Host *shost) void lpfc_host_attrib_init(struct Scsi_Host *shost)
{ {
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
...@@ -1906,6 +2146,25 @@ void lpfc_host_attrib_init(struct Scsi_Host *shost) ...@@ -1906,6 +2146,25 @@ void lpfc_host_attrib_init(struct Scsi_Host *shost)
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
} }
/**
* lpfc_enable_msix: Enable MSI-X interrupt mode.
* @phba: pointer to lpfc hba data structure.
*
* This routine is invoked to enable the MSI-X interrupt vectors. The kernel
* function pci_enable_msix() is called to enable the MSI-X vectors. Note that
* pci_enable_msix(), once invoked, enables either all or nothing, depending
* on the current availability of PCI vector resources. The device driver is
* responsible for calling the individual request_irq() to register each MSI-X
* vector with a interrupt handler, which is done in this function. Note that
* later when device is unloading, the driver should always call free_irq()
* on all MSI-X vectors it has done request_irq() on before calling
* pci_disable_msix(). Failure to do so results in a BUG_ON() and a device
* will be left with MSI-X enabled and leaks its vectors.
*
* Return codes
* 0 - sucessful
* other values - error
**/
static int static int
lpfc_enable_msix(struct lpfc_hba *phba) lpfc_enable_msix(struct lpfc_hba *phba)
{ {
...@@ -1935,6 +2194,13 @@ lpfc_enable_msix(struct lpfc_hba *phba) ...@@ -1935,6 +2194,13 @@ lpfc_enable_msix(struct lpfc_hba *phba)
return error; return error;
} }
/**
* lpfc_disable_msix: Disable MSI-X interrupt mode.
* @phba: pointer to lpfc hba data structure.
*
* This routine is invoked to release the MSI-X vectors and then disable the
* MSI-X interrupt mode.
**/
static void static void
lpfc_disable_msix(struct lpfc_hba *phba) lpfc_disable_msix(struct lpfc_hba *phba)
{ {
...@@ -1942,6 +2208,23 @@ lpfc_disable_msix(struct lpfc_hba *phba) ...@@ -1942,6 +2208,23 @@ lpfc_disable_msix(struct lpfc_hba *phba)
pci_disable_msix(phba->pcidev); pci_disable_msix(phba->pcidev);
} }
/**
* lpfc_pci_probe_one: lpfc PCI probe func to register device to PCI subsystem.
* @pdev: pointer to PCI device
* @pid: pointer to PCI device identifier
*
* This routine is to be registered to the kernel's PCI subsystem. When an
* Emulex HBA is presented in PCI bus, the kernel PCI subsystem looks at
* PCI device-specific information of the device and driver to see if the
* driver state that it can support this kind of device. If the match is
* successful, the driver core invokes this routine. If this routine
* determines it can claim the HBA, it does all the initialization that it
* needs to do to handle the HBA properly.
*
* Return code
* 0 - driver can claim the device
* negative value - driver can not claim the device
**/
static int __devinit static int __devinit
lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
{ {
...@@ -2262,6 +2545,14 @@ out: ...@@ -2262,6 +2545,14 @@ out:
return error; return error;
} }
/**
* lpfc_pci_remove_one: lpfc PCI func to unregister device from PCI subsystem.
* @pdev: pointer to PCI device
*
* This routine is to be registered to the kernel's PCI subsystem. When an
* Emulex HBA is removed from PCI bus. It perform all the necessary cleanup
* for the HBA device to be removed from the PCI subsystem properly.
**/
static void __devexit static void __devexit
lpfc_pci_remove_one(struct pci_dev *pdev) lpfc_pci_remove_one(struct pci_dev *pdev)
{ {
...@@ -2336,13 +2627,21 @@ lpfc_pci_remove_one(struct pci_dev *pdev) ...@@ -2336,13 +2627,21 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
} }
/** /**
* lpfc_io_error_detected - called when PCI error is detected * lpfc_io_error_detected: Driver method for handling PCI I/O error detected.
* @pdev: Pointer to PCI device * @pdev: pointer to PCI device.
* @state: The current pci conneection state * @state: the current PCI connection state.
* *
* This function is called after a PCI bus error affecting * This routine is registered to the PCI subsystem for error handling. This
* this device has been detected. * function is called by the PCI subsystem after a PCI bus error affecting
*/ * this device has been detected. When this function is invoked, it will
* need to stop all the I/Os and interrupt(s) to the device. Once that is
* done, it will return PCI_ERS_RESULT_NEED_RESET for the PCI subsystem to
* perform proper recovery as desired.
*
* Return codes
* PCI_ERS_RESULT_NEED_RESET - need to reset before recovery
* PCI_ERS_RESULT_DISCONNECT - device could not be recovered
**/
static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev, static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev,
pci_channel_state_t state) pci_channel_state_t state)
{ {
...@@ -2376,10 +2675,21 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev, ...@@ -2376,10 +2675,21 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev,
} }
/** /**
* lpfc_io_slot_reset - called after the pci bus has been reset. * lpfc_io_slot_reset: Restart a PCI device from scratch.
* @pdev: Pointer to PCI device * @pdev: pointer to PCI device.
*
* This routine is registered to the PCI subsystem for error handling. This is
* called after PCI bus has been reset to restart the PCI card from scratch,
* as if from a cold-boot. During the PCI subsystem error recovery, after the
* driver returns PCI_ERS_RESULT_NEED_RESET, the PCI subsystem will perform
* proper error recovery and then call this routine before calling the .resume
* method to recover the device. This function will initialize the HBA device,
* enable the interrupt, but it will just put the HBA to offline state without
* passing any I/O traffic.
* *
* Restart the card from scratch, as if from a cold-boot. * Return codes
* PCI_ERS_RESULT_RECOVERED - the device has been recovered
* PCI_ERS_RESULT_DISCONNECT - device could not be recovered
*/ */
static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev) static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
{ {
...@@ -2440,11 +2750,13 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev) ...@@ -2440,11 +2750,13 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
} }
/** /**
* lpfc_io_resume - called when traffic can start flowing again. * lpfc_io_resume: Resume PCI I/O operation.
* @pdev: Pointer to PCI device * @pdev: pointer to PCI device
* *
* This callback is called when the error recovery driver tells us that * This routine is registered to the PCI subsystem for error handling. It is
* its OK to resume normal operation. * called when kernel error recovery tells the lpfc driver that it is ok to
* resume normal PCI operation after PCI bus error recovery. After this call,
* traffic can start to flow from this device again.
*/ */
static void lpfc_io_resume(struct pci_dev *pdev) static void lpfc_io_resume(struct pci_dev *pdev)
{ {
...@@ -2540,6 +2852,18 @@ static struct pci_driver lpfc_driver = { ...@@ -2540,6 +2852,18 @@ static struct pci_driver lpfc_driver = {
.err_handler = &lpfc_err_handler, .err_handler = &lpfc_err_handler,
}; };
/**
* lpfc_init: lpfc module initialization routine.
*
* This routine is to be invoked when the lpfc module is loaded into the
* kernel. The special kernel macro module_init() is used to indicate the
* role of this routine to the kernel as lpfc module entry point.
*
* Return codes
* 0 - successful
* -ENOMEM - FC attach transport failed
* all others - failed
*/
static int __init static int __init
lpfc_init(void) lpfc_init(void)
{ {
...@@ -2573,6 +2897,13 @@ lpfc_init(void) ...@@ -2573,6 +2897,13 @@ lpfc_init(void)
return error; return error;
} }
/**
* lpfc_exit: lpfc module removal routine.
*
* This routine is invoked when the lpfc module is removed from the kernel.
* The special kernel macro module_exit() is used to indicate the role of
* this routine to the kernel as lpfc module exit point.
*/
static void __exit static void __exit
lpfc_exit(void) lpfc_exit(void)
{ {
......
...@@ -37,10 +37,20 @@ ...@@ -37,10 +37,20 @@
#include "lpfc_crtn.h" #include "lpfc_crtn.h"
#include "lpfc_compat.h" #include "lpfc_compat.h"
/**********************************************/ /**
* lpfc_dump_mem: Prepare a mailbox command for retrieving HBA's VPD memory.
/* mailbox command */ * @phba: pointer to lpfc hba data structure.
/**********************************************/ * @pmb: pointer to the driver internal queue element for mailbox command.
* @offset: offset for dumping VPD memory mailbox command.
*
* The dump mailbox command provides a method for the device driver to obtain
* various types of information from the HBA device.
*
* This routine prepares the mailbox command for dumping HBA Vital Product
* Data (VPD) memory. This mailbox command is to be used for retrieving a
* portion (DMP_RSP_SIZE bytes) of a HBA's VPD from the HBA at an address
* offset specified by the offset parameter.
**/
void void
lpfc_dump_mem(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint16_t offset) lpfc_dump_mem(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint16_t offset)
{ {
...@@ -65,10 +75,17 @@ lpfc_dump_mem(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint16_t offset) ...@@ -65,10 +75,17 @@ lpfc_dump_mem(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint16_t offset)
return; return;
} }
/**********************************************/ /**
/* lpfc_read_nv Issue a READ NVPARAM */ * lpfc_read_nv: Prepare a mailbox command for reading HBA's NVRAM param.
/* mailbox command */ * @phba: pointer to lpfc hba data structure.
/**********************************************/ * @pmb: pointer to the driver internal queue element for mailbox command.
*
* The read NVRAM mailbox command returns the HBA's non-volatile parameters
* that are used as defaults when the Fibre Channel link is brought on-line.
*
* This routine prepares the mailbox command for reading information stored
* in the HBA's NVRAM. Specifically, the HBA's WWNN and WWPN.
**/
void void
lpfc_read_nv(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) lpfc_read_nv(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
{ {
...@@ -81,10 +98,19 @@ lpfc_read_nv(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) ...@@ -81,10 +98,19 @@ lpfc_read_nv(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
return; return;
} }
/**********************************************/ /**
/* lpfc_config_async Issue a */ * lpfc_config_async: Prepare a mailbox command for enabling HBA async event.
/* MBX_ASYNC_EVT_ENABLE mailbox command */ * @phba: pointer to lpfc hba data structure.
/**********************************************/ * @pmb: pointer to the driver internal queue element for mailbox command.
* @ring: ring number for the asynchronous event to be configured.
*
* The asynchronous event enable mailbox command is used to enable the
* asynchronous event posting via the ASYNC_STATUS_CN IOCB response and
* specifies the default ring to which events are posted.
*
* This routine prepares the mailbox command for enabling HBA asynchronous
* event support on a IOCB ring.
**/
void void
lpfc_config_async(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, lpfc_config_async(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb,
uint32_t ring) uint32_t ring)
...@@ -99,10 +125,19 @@ lpfc_config_async(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, ...@@ -99,10 +125,19 @@ lpfc_config_async(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb,
return; return;
} }
/**********************************************/ /**
/* lpfc_heart_beat Issue a HEART_BEAT */ * lpfc_heart_beat: Prepare a mailbox command for heart beat.
/* mailbox command */ * @phba: pointer to lpfc hba data structure.
/**********************************************/ * @pmb: pointer to the driver internal queue element for mailbox command.
*
* The heart beat mailbox command is used to detect an unresponsive HBA, which
* is defined as any device where no error attention is sent and both mailbox
* and rings are not processed.
*
* This routine prepares the mailbox command for issuing a heart beat in the
* form of mailbox command to the HBA. The timely completion of the heart
* beat mailbox command indicates the health of the HBA.
**/
void void
lpfc_heart_beat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) lpfc_heart_beat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
{ {
...@@ -115,10 +150,26 @@ lpfc_heart_beat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) ...@@ -115,10 +150,26 @@ lpfc_heart_beat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
return; return;
} }
/**********************************************/ /**
/* lpfc_read_la Issue a READ LA */ * lpfc_read_la: Prepare a mailbox command for reading HBA link attention.
/* mailbox command */ * @phba: pointer to lpfc hba data structure.
/**********************************************/ * @pmb: pointer to the driver internal queue element for mailbox command.
* @mp: DMA buffer memory for reading the link attention information into.
*
* The read link attention mailbox command is issued to read the Link Event
* Attention information indicated by the HBA port when the Link Event bit
* of the Host Attention (HSTATT) register is set to 1. A Link Event
* Attention occurs based on an exception detected at the Fibre Channel link
* interface.
*
* This routine prepares the mailbox command for reading HBA link attention
* information. A DMA memory has been set aside and address passed to the
* HBA through @mp for the HBA to DMA link attention information into the
* memory as part of the execution of the mailbox command.
*
* Return codes
* 0 - Success (currently always return 0)
**/
int int
lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, struct lpfc_dmabuf *mp) lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, struct lpfc_dmabuf *mp)
{ {
...@@ -143,10 +194,21 @@ lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, struct lpfc_dmabuf *mp) ...@@ -143,10 +194,21 @@ lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, struct lpfc_dmabuf *mp)
return (0); return (0);
} }
/**********************************************/ /**
/* lpfc_clear_la Issue a CLEAR LA */ * lpfc_clear_la: Prepare a mailbox command for clearing HBA link attention.
/* mailbox command */ * @phba: pointer to lpfc hba data structure.
/**********************************************/ * @pmb: pointer to the driver internal queue element for mailbox command.
*
* The clear link attention mailbox command is issued to clear the link event
* attention condition indicated by the Link Event bit of the Host Attention
* (HSTATT) register. The link event attention condition is cleared only if
* the event tag specified matches that of the current link event counter.
* The current event tag is read using the read link attention event mailbox
* command.
*
* This routine prepares the mailbox command for clearing HBA link attention
* information.
**/
void void
lpfc_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) lpfc_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
{ {
...@@ -161,10 +223,20 @@ lpfc_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) ...@@ -161,10 +223,20 @@ lpfc_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
return; return;
} }
/**************************************************/ /**
/* lpfc_config_link Issue a CONFIG LINK */ * lpfc_config_link: Prepare a mailbox command for configuring link on a HBA.
/* mailbox command */ * @phba: pointer to lpfc hba data structure.
/**************************************************/ * @pmb: pointer to the driver internal queue element for mailbox command.
*
* The configure link mailbox command is used before the initialize link
* mailbox command to override default value and to configure link-oriented
* parameters such as DID address and various timers. Typically, this
* command would be used after an F_Port login to set the returned DID address
* and the fabric timeout values. This command is not valid before a configure
* port command has configured the HBA port.
*
* This routine prepares the mailbox command for configuring link on a HBA.
**/
void void
lpfc_config_link(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) lpfc_config_link(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
{ {
...@@ -199,10 +271,20 @@ lpfc_config_link(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) ...@@ -199,10 +271,20 @@ lpfc_config_link(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
return; return;
} }
/**********************************************/ /**
/* lpfc_init_link Issue an INIT LINK */ * lpfc_init_link: Prepare a mailbox command for initialize link on a HBA.
/* mailbox command */ * @phba: pointer to lpfc hba data structure.
/**********************************************/ * @pmb: pointer to the driver internal queue element for mailbox command.
* @topology: the link topology for the link to be initialized to.
* @linkspeed: the link speed for the link to be initialized to.
*
* The initialize link mailbox command is used to initialize the Fibre
* Channel link. This command must follow a configure port command that
* establishes the mode of operation.
*
* This routine prepares the mailbox command for initializing link on a HBA
* with the specified link topology and speed.
**/
void void
lpfc_init_link(struct lpfc_hba * phba, lpfc_init_link(struct lpfc_hba * phba,
LPFC_MBOXQ_t * pmb, uint32_t topology, uint32_t linkspeed) LPFC_MBOXQ_t * pmb, uint32_t topology, uint32_t linkspeed)
...@@ -269,10 +351,27 @@ lpfc_init_link(struct lpfc_hba * phba, ...@@ -269,10 +351,27 @@ lpfc_init_link(struct lpfc_hba * phba,
return; return;
} }
/**********************************************/ /**
/* lpfc_read_sparam Issue a READ SPARAM */ * lpfc_read_sparam: Prepare a mailbox command for reading HBA parameters.
/* mailbox command */ * @phba: pointer to lpfc hba data structure.
/**********************************************/ * @pmb: pointer to the driver internal queue element for mailbox command.
* @vpi: virtual N_Port identifier.
*
* The read service parameter mailbox command is used to read the HBA port
* service parameters. The service parameters are read into the buffer
* specified directly by a BDE in the mailbox command. These service
* parameters may then be used to build the payload of an N_Port/F_POrt
* login request and reply (LOGI/ACC).
*
* This routine prepares the mailbox command for reading HBA port service
* parameters. The DMA memory is allocated in this function and the addresses
* are populated into the mailbox command for the HBA to DMA the service
* parameters into.
*
* Return codes
* 0 - Success
* 1 - DMA memory allocation failed
**/
int int
lpfc_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, int vpi) lpfc_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, int vpi)
{ {
...@@ -312,10 +411,21 @@ lpfc_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, int vpi) ...@@ -312,10 +411,21 @@ lpfc_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, int vpi)
return (0); return (0);
} }
/********************************************/ /**
/* lpfc_unreg_did Issue a UNREG_DID */ * lpfc_unreg_did: Prepare a mailbox command for unregistering DID.
/* mailbox command */ * @phba: pointer to lpfc hba data structure.
/********************************************/ * @vpi: virtual N_Port identifier.
* @did: remote port identifier.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
* The unregister DID mailbox command is used to unregister an N_Port/F_Port
* login for an unknown RPI by specifying the DID of a remote port. This
* command frees an RPI context in the HBA port. This has the effect of
* performing an implicit N_Port/F_Port logout.
*
* This routine prepares the mailbox command for unregistering a remote
* N_Port/F_Port (DID) login.
**/
void void
lpfc_unreg_did(struct lpfc_hba * phba, uint16_t vpi, uint32_t did, lpfc_unreg_did(struct lpfc_hba * phba, uint16_t vpi, uint32_t did,
LPFC_MBOXQ_t * pmb) LPFC_MBOXQ_t * pmb)
...@@ -333,10 +443,19 @@ lpfc_unreg_did(struct lpfc_hba * phba, uint16_t vpi, uint32_t did, ...@@ -333,10 +443,19 @@ lpfc_unreg_did(struct lpfc_hba * phba, uint16_t vpi, uint32_t did,
return; return;
} }
/**********************************************/ /**
/* lpfc_read_nv Issue a READ CONFIG */ * lpfc_read_config: Prepare a mailbox command for reading HBA configuration.
/* mailbox command */ * @phba: pointer to lpfc hba data structure.
/**********************************************/ * @pmb: pointer to the driver internal queue element for mailbox command.
*
* The read configuration mailbox command is used to read the HBA port
* configuration parameters. This mailbox command provides a method for
* seeing any parameters that may have changed via various configuration
* mailbox commands.
*
* This routine prepares the mailbox command for reading out HBA configuration
* parameters.
**/
void void
lpfc_read_config(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) lpfc_read_config(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
{ {
...@@ -350,10 +469,18 @@ lpfc_read_config(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) ...@@ -350,10 +469,18 @@ lpfc_read_config(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
return; return;
} }
/*************************************************/ /**
/* lpfc_read_lnk_stat Issue a READ LINK STATUS */ * lpfc_read_lnk_stat: Prepare a mailbox command for reading HBA link stats.
/* mailbox command */ * @phba: pointer to lpfc hba data structure.
/*************************************************/ * @pmb: pointer to the driver internal queue element for mailbox command.
*
* The read link status mailbox command is used to read the link status from
* the HBA. Link status includes all link-related error counters. These
* counters are maintained by the HBA and originated in the link hardware
* unit. Note that all of these counters wrap.
*
* This routine prepares the mailbox command for reading out HBA link status.
**/
void void
lpfc_read_lnk_stat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) lpfc_read_lnk_stat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
{ {
...@@ -367,10 +494,30 @@ lpfc_read_lnk_stat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) ...@@ -367,10 +494,30 @@ lpfc_read_lnk_stat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
return; return;
} }
/********************************************/ /**
/* lpfc_reg_login Issue a REG_LOGIN */ * lpfc_reg_login: Prepare a mailbox command for registering remote login.
/* mailbox command */ * @phba: pointer to lpfc hba data structure.
/********************************************/ * @vpi: virtual N_Port identifier.
* @did: remote port identifier.
* @param: pointer to memory holding the server parameters.
* @pmb: pointer to the driver internal queue element for mailbox command.
* @flag: action flag to be passed back for the complete function.
*
* The registration login mailbox command is used to register an N_Port or
* F_Port login. This registration allows the HBA to cache the remote N_Port
* service parameters internally and thereby make the appropriate FC-2
* decisions. The remote port service parameters are handed off by the driver
* to the HBA using a descriptor entry that directly identifies a buffer in
* host memory. In exchange, the HBA returns an RPI identifier.
*
* This routine prepares the mailbox command for registering remote port login.
* The function allocates DMA buffer for passing the service parameters to the
* HBA with the mailbox command.
*
* Return codes
* 0 - Success
* 1 - DMA memory allocation failed
**/
int int
lpfc_reg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t did, lpfc_reg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t did,
uint8_t *param, LPFC_MBOXQ_t *pmb, uint32_t flag) uint8_t *param, LPFC_MBOXQ_t *pmb, uint32_t flag)
...@@ -418,10 +565,20 @@ lpfc_reg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t did, ...@@ -418,10 +565,20 @@ lpfc_reg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t did,
return (0); return (0);
} }
/**********************************************/ /**
/* lpfc_unreg_login Issue a UNREG_LOGIN */ * lpfc_unreg_login: Prepare a mailbox command for unregistering remote login.
/* mailbox command */ * @phba: pointer to lpfc hba data structure.
/**********************************************/ * @vpi: virtual N_Port identifier.
* @rpi: remote port identifier
* @pmb: pointer to the driver internal queue element for mailbox command.
*
* The unregistration login mailbox command is used to unregister an N_Port
* or F_Port login. This command frees an RPI context in the HBA. It has the
* effect of performing an implicit N_Port/F_Port logout.
*
* This routine prepares the mailbox command for unregistering remote port
* login.
**/
void void
lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi, lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi,
LPFC_MBOXQ_t * pmb) LPFC_MBOXQ_t * pmb)
...@@ -440,10 +597,21 @@ lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi, ...@@ -440,10 +597,21 @@ lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi,
return; return;
} }
/**************************************************/ /**
/* lpfc_reg_vpi Issue a REG_VPI */ * lpfc_reg_vpi: Prepare a mailbox command for registering vport identifier.
/* mailbox command */ * @phba: pointer to lpfc hba data structure.
/**************************************************/ * @vpi: virtual N_Port identifier.
* @sid: Fibre Channel S_ID (N_Port_ID assigned to a virtual N_Port).
* @pmb: pointer to the driver internal queue element for mailbox command.
*
* The registration vport identifier mailbox command is used to activate a
* virtual N_Port after it has acquired an N_Port_ID. The HBA validates the
* N_Port_ID against the information in the selected virtual N_Port context
* block and marks it active to allow normal processing of IOCB commands and
* received unsolicited exchanges.
*
* This routine prepares the mailbox command for registering a virtual N_Port.
**/
void void
lpfc_reg_vpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t sid, lpfc_reg_vpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t sid,
LPFC_MBOXQ_t *pmb) LPFC_MBOXQ_t *pmb)
...@@ -461,10 +629,22 @@ lpfc_reg_vpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t sid, ...@@ -461,10 +629,22 @@ lpfc_reg_vpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t sid,
} }
/**************************************************/ /**
/* lpfc_unreg_vpi Issue a UNREG_VNPI */ * lpfc_unreg_vpi: Prepare a mailbox command for unregistering vport id.
/* mailbox command */ * @phba: pointer to lpfc hba data structure.
/**************************************************/ * @vpi: virtual N_Port identifier.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
* The unregistration vport identifier mailbox command is used to inactivate
* a virtual N_Port. The driver must have logged out and unregistered all
* remote N_Ports to abort any activity on the virtual N_Port. The HBA will
* unregisters any default RPIs associated with the specified vpi, aborting
* any active exchanges. The HBA will post the mailbox response after making
* the virtual N_Port inactive.
*
* This routine prepares the mailbox command for unregistering a virtual
* N_Port.
**/
void void
lpfc_unreg_vpi(struct lpfc_hba *phba, uint16_t vpi, LPFC_MBOXQ_t *pmb) lpfc_unreg_vpi(struct lpfc_hba *phba, uint16_t vpi, LPFC_MBOXQ_t *pmb)
{ {
...@@ -479,6 +659,13 @@ lpfc_unreg_vpi(struct lpfc_hba *phba, uint16_t vpi, LPFC_MBOXQ_t *pmb) ...@@ -479,6 +659,13 @@ lpfc_unreg_vpi(struct lpfc_hba *phba, uint16_t vpi, LPFC_MBOXQ_t *pmb)
} }
/**
* lpfc_config_pcb_setup: Set up IOCB rings in the Port Control Block (PCB)
* @phba: pointer to lpfc hba data structure.
*
* This routine sets up and initializes the IOCB rings in the Port Control
* Block (PCB).
**/
static void static void
lpfc_config_pcb_setup(struct lpfc_hba * phba) lpfc_config_pcb_setup(struct lpfc_hba * phba)
{ {
...@@ -536,6 +723,20 @@ lpfc_config_pcb_setup(struct lpfc_hba * phba) ...@@ -536,6 +723,20 @@ lpfc_config_pcb_setup(struct lpfc_hba * phba)
} }
} }
/**
* lpfc_read_rev: Prepare a mailbox command for reading HBA revision.
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
* The read revision mailbox command is used to read the revision levels of
* the HBA components. These components include hardware units, resident
* firmware, and available firmware. HBAs that supports SLI-3 mode of
* operation provide different response information depending on the version
* requested by the driver.
*
* This routine prepares the mailbox command for reading HBA revision
* information.
**/
void void
lpfc_read_rev(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) lpfc_read_rev(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
{ {
...@@ -548,6 +749,16 @@ lpfc_read_rev(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) ...@@ -548,6 +749,16 @@ lpfc_read_rev(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
return; return;
} }
/**
* lpfc_build_hbq_profile2: Set up the HBQ Selection Profile 2.
* @hbqmb: pointer to the HBQ configuration data structure in mailbox command.
* @hbq_desc: pointer to the HBQ selection profile descriptor.
*
* The Host Buffer Queue (HBQ) Selection Profile 2 specifies that the HBA
* tests the incoming frames' R_CTL/TYPE fields with works 10:15 and performs
* the Sequence Length Test using the fields in the Selection Profile 2
* extension in words 20:31.
**/
static void static void
lpfc_build_hbq_profile2(struct config_hbq_var *hbqmb, lpfc_build_hbq_profile2(struct config_hbq_var *hbqmb,
struct lpfc_hbq_init *hbq_desc) struct lpfc_hbq_init *hbq_desc)
...@@ -557,6 +768,16 @@ lpfc_build_hbq_profile2(struct config_hbq_var *hbqmb, ...@@ -557,6 +768,16 @@ lpfc_build_hbq_profile2(struct config_hbq_var *hbqmb,
hbqmb->profiles.profile2.seqlenoff = hbq_desc->seqlenoff; hbqmb->profiles.profile2.seqlenoff = hbq_desc->seqlenoff;
} }
/**
* lpfc_build_hbq_profile3: Set up the HBQ Selection Profile 3.
* @hbqmb: pointer to the HBQ configuration data structure in mailbox command.
* @hbq_desc: pointer to the HBQ selection profile descriptor.
*
* The Host Buffer Queue (HBQ) Selection Profile 3 specifies that the HBA
* tests the incoming frame's R_CTL/TYPE fields with words 10:15 and performs
* the Sequence Length Test and Byte Field Test using the fields in the
* Selection Profile 3 extension in words 20:31.
**/
static void static void
lpfc_build_hbq_profile3(struct config_hbq_var *hbqmb, lpfc_build_hbq_profile3(struct config_hbq_var *hbqmb,
struct lpfc_hbq_init *hbq_desc) struct lpfc_hbq_init *hbq_desc)
...@@ -569,6 +790,17 @@ lpfc_build_hbq_profile3(struct config_hbq_var *hbqmb, ...@@ -569,6 +790,17 @@ lpfc_build_hbq_profile3(struct config_hbq_var *hbqmb,
sizeof(hbqmb->profiles.profile3.cmdmatch)); sizeof(hbqmb->profiles.profile3.cmdmatch));
} }
/**
* lpfc_build_hbq_profile5: Set up the HBQ Selection Profile 5.
* @hbqmb: pointer to the HBQ configuration data structure in mailbox command.
* @hbq_desc: pointer to the HBQ selection profile descriptor.
*
* The Host Buffer Queue (HBQ) Selection Profile 5 specifies a header HBQ. The
* HBA tests the initial frame of an incoming sequence using the frame's
* R_CTL/TYPE fields with words 10:15 and performs the Sequence Length Test
* and Byte Field Test using the fields in the Selection Profile 5 extension
* words 20:31.
**/
static void static void
lpfc_build_hbq_profile5(struct config_hbq_var *hbqmb, lpfc_build_hbq_profile5(struct config_hbq_var *hbqmb,
struct lpfc_hbq_init *hbq_desc) struct lpfc_hbq_init *hbq_desc)
...@@ -581,6 +813,20 @@ lpfc_build_hbq_profile5(struct config_hbq_var *hbqmb, ...@@ -581,6 +813,20 @@ lpfc_build_hbq_profile5(struct config_hbq_var *hbqmb,
sizeof(hbqmb->profiles.profile5.cmdmatch)); sizeof(hbqmb->profiles.profile5.cmdmatch));
} }
/**
* lpfc_config_hbq: Prepare a mailbox command for configuring an HBQ.
* @phba: pointer to lpfc hba data structure.
* @id: HBQ identifier.
* @hbq_desc: pointer to the HBA descriptor data structure.
* @hbq_entry_index: index of the HBQ entry data structures.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
* The configure HBQ (Host Buffer Queue) mailbox command is used to configure
* an HBQ. The configuration binds events that require buffers to a particular
* ring and HBQ based on a selection profile.
*
* This routine prepares the mailbox command for configuring an HBQ.
**/
void void
lpfc_config_hbq(struct lpfc_hba *phba, uint32_t id, lpfc_config_hbq(struct lpfc_hba *phba, uint32_t id,
struct lpfc_hbq_init *hbq_desc, struct lpfc_hbq_init *hbq_desc,
...@@ -641,8 +887,23 @@ lpfc_config_hbq(struct lpfc_hba *phba, uint32_t id, ...@@ -641,8 +887,23 @@ lpfc_config_hbq(struct lpfc_hba *phba, uint32_t id,
return; return;
} }
/**
* lpfc_config_ring: Prepare a mailbox command for configuring an IOCB ring.
* @phba: pointer to lpfc hba data structure.
* @ring:
* @pmb: pointer to the driver internal queue element for mailbox command.
*
* The configure ring mailbox command is used to configure an IOCB ring. This
* configuration binds from one to six of HBA RC_CTL/TYPE mask entries to the
* ring. This is used to map incoming sequences to a particular ring whose
* RC_CTL/TYPE mask entry matches that of the sequence. The driver should not
* attempt to configure a ring whose number is greater than the number
* specified in the Port Control Block (PCB). It is an error to issue the
* configure ring command more than once with the same ring number. The HBA
* returns an error if the driver attempts this.
*
* This routine prepares the mailbox command for configuring IOCB ring.
**/
void void
lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb) lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb)
{ {
...@@ -684,6 +945,20 @@ lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb) ...@@ -684,6 +945,20 @@ lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb)
return; return;
} }
/**
* lpfc_config_port: Prepare a mailbox command for configuring port.
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
* The configure port mailbox command is used to identify the Port Control
* Block (PCB) in the driver memory. After this command is issued, the
* driver must not access the mailbox in the HBA without first resetting
* the HBA. The HBA may copy the PCB information to internal storage for
* subsequent use; the driver can not change the PCB information unless it
* resets the HBA.
*
* This routine prepares the mailbox command for configuring port.
**/
void void
lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{ {
...@@ -839,6 +1114,21 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -839,6 +1114,21 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
sizeof(PCB_t)); sizeof(PCB_t));
} }
/**
* lpfc_kill_board: Prepare a mailbox command for killing board.
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
* The kill board mailbox command is used to tell firmware to perform a
* graceful shutdown of a channel on a specified board to prepare for reset.
* When the kill board mailbox command is received, the ER3 bit is set to 1
* in the Host Status register and the ER Attention bit is set to 1 in the
* Host Attention register of the HBA function that received the kill board
* command.
*
* This routine prepares the mailbox command for killing the board in
* preparation for a graceful shutdown.
**/
void void
lpfc_kill_board(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) lpfc_kill_board(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
{ {
...@@ -850,6 +1140,16 @@ lpfc_kill_board(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) ...@@ -850,6 +1140,16 @@ lpfc_kill_board(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
return; return;
} }
/**
* lpfc_mbox_put: Put a mailbox cmd into the tail of driver's mailbox queue.
* @phba: pointer to lpfc hba data structure.
* @mbq: pointer to the driver internal queue element for mailbox command.
*
* Driver maintains a internal mailbox command queue implemented as a linked
* list. When a mailbox command is issued, it shall be put into the mailbox
* command queue such that they shall be processed orderly as HBA can process
* one mailbox command at a time.
**/
void void
lpfc_mbox_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq) lpfc_mbox_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq)
{ {
...@@ -864,6 +1164,20 @@ lpfc_mbox_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq) ...@@ -864,6 +1164,20 @@ lpfc_mbox_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq)
return; return;
} }
/**
* lpfc_mbox_get: Remove a mailbox cmd from the head of driver's mailbox queue.
* @phba: pointer to lpfc hba data structure.
*
* Driver maintains a internal mailbox command queue implemented as a linked
* list. When a mailbox command is issued, it shall be put into the mailbox
* command queue such that they shall be processed orderly as HBA can process
* one mailbox command at a time. After HBA finished processing a mailbox
* command, the driver will remove a pending mailbox command from the head of
* the mailbox command queue and send to the HBA for processing.
*
* Return codes
* pointer to the driver internal queue element for mailbox command.
**/
LPFC_MBOXQ_t * LPFC_MBOXQ_t *
lpfc_mbox_get(struct lpfc_hba * phba) lpfc_mbox_get(struct lpfc_hba * phba)
{ {
...@@ -877,6 +1191,17 @@ lpfc_mbox_get(struct lpfc_hba * phba) ...@@ -877,6 +1191,17 @@ lpfc_mbox_get(struct lpfc_hba * phba)
return mbq; return mbq;
} }
/**
* lpfc_mbox_cmpl_put: Put mailbox command into mailbox command complete list.
* @phba: pointer to lpfc hba data structure.
* @mbq: pointer to the driver internal queue element for mailbox command.
*
* This routine put the completed mailbox command into the mailbox command
* complete list. This routine is called from driver interrupt handler
* context.The mailbox complete list is used by the driver worker thread
* to process mailbox complete callback functions outside the driver interrupt
* handler.
**/
void void
lpfc_mbox_cmpl_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq) lpfc_mbox_cmpl_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq)
{ {
...@@ -887,6 +1212,17 @@ lpfc_mbox_cmpl_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq) ...@@ -887,6 +1212,17 @@ lpfc_mbox_cmpl_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq)
return; return;
} }
/**
* lpfc_mbox_tmo_val: Retrieve mailbox command timeout value.
* @phba: pointer to lpfc hba data structure.
* @cmd: mailbox command code.
*
* This routine retrieves the proper timeout value according to the mailbox
* command code.
*
* Return codes
* Timeout value to be used for the given mailbox command
**/
int int
lpfc_mbox_tmo_val(struct lpfc_hba *phba, int cmd) lpfc_mbox_tmo_val(struct lpfc_hba *phba, int cmd)
{ {
......
/******************************************************************* /*******************************************************************
* This file is part of the Emulex Linux Device Driver for * * This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. * * Fibre Channel Host Bus Adapters. *
* Copyright (C) 2004-2006 Emulex. All rights reserved. * * Copyright (C) 2004-2008 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. * * EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com * * www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig * * Portions Copyright (C) 2004-2005 Christoph Hellwig *
...@@ -39,7 +39,21 @@ ...@@ -39,7 +39,21 @@
#define LPFC_MEM_POOL_SIZE 64 /* max elem in non-DMA safety pool */ #define LPFC_MEM_POOL_SIZE 64 /* max elem in non-DMA safety pool */
/**
* lpfc_mem_alloc: create and allocate all PCI and memory pools
* @phba: HBA to allocate pools for
*
* Description: Creates and allocates PCI pools lpfc_scsi_dma_buf_pool,
* lpfc_mbuf_pool, lpfc_hbq_pool. Creates and allocates kmalloc-backed mempools
* for LPFC_MBOXQ_t and lpfc_nodelist. Also allocates the VPI bitmask.
*
* Notes: Not interrupt-safe. Must be called with no locks held. If any
* allocation fails, frees all successfully allocated memory before returning.
*
* Returns:
* 0 on success
* -ENOMEM on failure (if any memory allocations fail)
**/
int int
lpfc_mem_alloc(struct lpfc_hba * phba) lpfc_mem_alloc(struct lpfc_hba * phba)
{ {
...@@ -120,6 +134,16 @@ lpfc_mem_alloc(struct lpfc_hba * phba) ...@@ -120,6 +134,16 @@ lpfc_mem_alloc(struct lpfc_hba * phba)
return -ENOMEM; return -ENOMEM;
} }
/**
* lpfc_mem_free: Frees all PCI and memory allocated by lpfc_mem_alloc
* @phba: HBA to free memory for
*
* Description: Frees PCI pools lpfc_scsi_dma_buf_pool, lpfc_mbuf_pool,
* lpfc_hbq_pool. Frees kmalloc-backed mempools for LPFC_MBOXQ_t and
* lpfc_nodelist. Also frees the VPI bitmask.
*
* Returns: None
**/
void void
lpfc_mem_free(struct lpfc_hba * phba) lpfc_mem_free(struct lpfc_hba * phba)
{ {
...@@ -181,12 +205,29 @@ lpfc_mem_free(struct lpfc_hba * phba) ...@@ -181,12 +205,29 @@ lpfc_mem_free(struct lpfc_hba * phba)
phba->lpfc_scsi_dma_buf_pool = NULL; phba->lpfc_scsi_dma_buf_pool = NULL;
phba->lpfc_mbuf_pool = NULL; phba->lpfc_mbuf_pool = NULL;
/* Free the iocb lookup array */ /* Free the iocb lookup array */
kfree(psli->iocbq_lookup); kfree(psli->iocbq_lookup);
psli->iocbq_lookup = NULL; psli->iocbq_lookup = NULL;
} }
/**
* lpfc_mbuf_alloc: Allocate an mbuf from the lpfc_mbuf_pool PCI pool
* @phba: HBA which owns the pool to allocate from
* @mem_flags: indicates if this is a priority (MEM_PRI) allocation
* @handle: used to return the DMA-mapped address of the mbuf
*
* Description: Allocates a DMA-mapped buffer from the lpfc_mbuf_pool PCI pool.
* Allocates from generic pci_pool_alloc function first and if that fails and
* mem_flags has MEM_PRI set (the only defined flag), returns an mbuf from the
* HBA's pool.
*
* Notes: Not interrupt-safe. Must be called with no locks held. Takes
* phba->hbalock.
*
* Returns:
* pointer to the allocated mbuf on success
* NULL on failure
**/
void * void *
lpfc_mbuf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle) lpfc_mbuf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle)
{ {
...@@ -206,6 +247,20 @@ lpfc_mbuf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle) ...@@ -206,6 +247,20 @@ lpfc_mbuf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle)
return ret; return ret;
} }
/**
* __lpfc_mem_free: Free an mbuf from the lpfc_mbuf_pool PCI pool (locked)
* @phba: HBA which owns the pool to return to
* @virt: mbuf to free
* @dma: the DMA-mapped address of the lpfc_mbuf_pool to be freed
*
* Description: Returns an mbuf lpfc_mbuf_pool to the lpfc_mbuf_safety_pool if
* it is below its max_count, frees the mbuf otherwise.
*
* Notes: Must be called with phba->hbalock held to synchronize access to
* lpfc_mbuf_safety_pool.
*
* Returns: None
**/
void void
__lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma) __lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
{ {
...@@ -221,7 +276,21 @@ __lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma) ...@@ -221,7 +276,21 @@ __lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
return; return;
} }
/**
* lpfc_mem_free: Free an mbuf from the lpfc_mbuf_pool PCI pool (unlocked)
* @phba: HBA which owns the pool to return to
* @virt: mbuf to free
* @dma: the DMA-mapped address of the lpfc_mbuf_pool to be freed
*
* Description: Returns an mbuf lpfc_mbuf_pool to the lpfc_mbuf_safety_pool if
* it is below its max_count, frees the mbuf otherwise.
*
* Notes: Takes phba->hbalock. Can be called with or without other locks held.
*
* Returns: None
**/
void void
lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma) lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
{ {
unsigned long iflags; unsigned long iflags;
...@@ -232,6 +301,19 @@ lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma) ...@@ -232,6 +301,19 @@ lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
return; return;
} }
/**
* lpfc_els_hbq_alloc: Allocate an HBQ buffer
* @phba: HBA to allocate HBQ buffer for
*
* Description: Allocates a DMA-mapped HBQ buffer from the lpfc_hbq_pool PCI
* pool along a non-DMA-mapped container for it.
*
* Notes: Not interrupt-safe. Must be called with no locks held.
*
* Returns:
* pointer to HBQ on success
* NULL on failure
**/
struct hbq_dmabuf * struct hbq_dmabuf *
lpfc_els_hbq_alloc(struct lpfc_hba *phba) lpfc_els_hbq_alloc(struct lpfc_hba *phba)
{ {
...@@ -251,6 +333,18 @@ lpfc_els_hbq_alloc(struct lpfc_hba *phba) ...@@ -251,6 +333,18 @@ lpfc_els_hbq_alloc(struct lpfc_hba *phba)
return hbqbp; return hbqbp;
} }
/**
* lpfc_mem_hbq_free: Frees an HBQ buffer allocated with lpfc_els_hbq_alloc
* @phba: HBA buffer was allocated for
* @hbqbp: HBQ container returned by lpfc_els_hbq_alloc
*
* Description: Frees both the container and the DMA-mapped buffer returned by
* lpfc_els_hbq_alloc.
*
* Notes: Can be called with or without locks held.
*
* Returns: None
**/
void void
lpfc_els_hbq_free(struct lpfc_hba *phba, struct hbq_dmabuf *hbqbp) lpfc_els_hbq_free(struct lpfc_hba *phba, struct hbq_dmabuf *hbqbp)
{ {
...@@ -259,7 +353,18 @@ lpfc_els_hbq_free(struct lpfc_hba *phba, struct hbq_dmabuf *hbqbp) ...@@ -259,7 +353,18 @@ lpfc_els_hbq_free(struct lpfc_hba *phba, struct hbq_dmabuf *hbqbp)
return; return;
} }
/* This is ONLY called for the LPFC_ELS_HBQ */ /**
* lpfc_in_buf_free: Free a DMA buffer
* @phba: HBA buffer is associated with
* @mp: Buffer to free
*
* Description: Frees the given DMA buffer in the appropriate way given if the
* HBA is running in SLI3 mode with HBQs enabled.
*
* Notes: Takes phba->hbalock. Can be called with or without other locks held.
*
* Returns: None
**/
void void
lpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp) lpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp)
{ {
......
...@@ -66,10 +66,16 @@ typedef enum _lpfc_iocb_type { ...@@ -66,10 +66,16 @@ typedef enum _lpfc_iocb_type {
LPFC_ABORT_IOCB LPFC_ABORT_IOCB
} lpfc_iocb_type; } lpfc_iocb_type;
/* SLI-2/SLI-3 provide different sized iocbs. Given a pointer /**
* to the start of the ring, and the slot number of the * lpfc_cmd_iocb: Get next command iocb entry in the ring.
* desired iocb entry, calc a pointer to that entry. * @phba: Pointer to HBA context object.
*/ * @pring: Pointer to driver SLI ring object.
*
* This function returns pointer to next command iocb entry
* in the command ring. The caller must hold hbalock to prevent
* other threads consume the next command iocb.
* SLI-2/SLI-3 provide different sized iocbs.
**/
static inline IOCB_t * static inline IOCB_t *
lpfc_cmd_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) lpfc_cmd_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{ {
...@@ -77,6 +83,16 @@ lpfc_cmd_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) ...@@ -77,6 +83,16 @@ lpfc_cmd_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
pring->cmdidx * phba->iocb_cmd_size); pring->cmdidx * phba->iocb_cmd_size);
} }
/**
* lpfc_resp_iocb: Get next response iocb entry in the ring.
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
* This function returns pointer to next response iocb entry
* in the response ring. The caller must hold hbalock to make sure
* that no other thread consume the next response iocb.
* SLI-2/SLI-3 provide different sized iocbs.
**/
static inline IOCB_t * static inline IOCB_t *
lpfc_resp_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) lpfc_resp_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{ {
...@@ -84,6 +100,15 @@ lpfc_resp_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) ...@@ -84,6 +100,15 @@ lpfc_resp_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
pring->rspidx * phba->iocb_rsp_size); pring->rspidx * phba->iocb_rsp_size);
} }
/**
* __lpfc_sli_get_iocbq: Allocates an iocb object from iocb pool.
* @phba: Pointer to HBA context object.
*
* This function is called with hbalock held. This function
* allocates a new driver iocb object from the iocb pool. If the
* allocation is successful, it returns pointer to the newly
* allocated iocb object else it returns NULL.
**/
static struct lpfc_iocbq * static struct lpfc_iocbq *
__lpfc_sli_get_iocbq(struct lpfc_hba *phba) __lpfc_sli_get_iocbq(struct lpfc_hba *phba)
{ {
...@@ -94,6 +119,15 @@ __lpfc_sli_get_iocbq(struct lpfc_hba *phba) ...@@ -94,6 +119,15 @@ __lpfc_sli_get_iocbq(struct lpfc_hba *phba)
return iocbq; return iocbq;
} }
/**
* lpfc_sli_get_iocbq: Allocates an iocb object from iocb pool.
* @phba: Pointer to HBA context object.
*
* This function is called with no lock held. This function
* allocates a new driver iocb object from the iocb pool. If the
* allocation is successful, it returns pointer to the newly
* allocated iocb object else it returns NULL.
**/
struct lpfc_iocbq * struct lpfc_iocbq *
lpfc_sli_get_iocbq(struct lpfc_hba *phba) lpfc_sli_get_iocbq(struct lpfc_hba *phba)
{ {
...@@ -106,6 +140,16 @@ lpfc_sli_get_iocbq(struct lpfc_hba *phba) ...@@ -106,6 +140,16 @@ lpfc_sli_get_iocbq(struct lpfc_hba *phba)
return iocbq; return iocbq;
} }
/**
* __lpfc_sli_release_iocbq: Release iocb to the iocb pool.
* @phba: Pointer to HBA context object.
* @iocbq: Pointer to driver iocb object.
*
* This function is called with hbalock held to release driver
* iocb object to the iocb pool. The iotag in the iocb object
* does not change for each use of the iocb object. This function
* clears all other fields of the iocb object when it is freed.
**/
static void static void
__lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) __lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
{ {
...@@ -118,6 +162,14 @@ __lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) ...@@ -118,6 +162,14 @@ __lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
list_add_tail(&iocbq->list, &phba->lpfc_iocb_list); list_add_tail(&iocbq->list, &phba->lpfc_iocb_list);
} }
/**
* lpfc_sli_release_iocbq: Release iocb to the iocb pool.
* @phba: Pointer to HBA context object.
* @iocbq: Pointer to driver iocb object.
*
* This function is called with no lock held to release the iocb to
* iocb pool.
**/
void void
lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
{ {
...@@ -131,10 +183,21 @@ lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) ...@@ -131,10 +183,21 @@ lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
spin_unlock_irqrestore(&phba->hbalock, iflags); spin_unlock_irqrestore(&phba->hbalock, iflags);
} }
/* /**
* Translate the iocb command to an iocb command type used to decide the final * lpfc_sli_iocb_cmd_type: Get the iocb type.
* disposition of each completed IOCB. * @iocb_cmnd : iocb command code.
*/ *
* This function is called by ring event handler function to get the iocb type.
* This function translates the iocb command to an iocb command type used to
* decide the final disposition of each completed IOCB.
* The function returns
* LPFC_UNKNOWN_IOCB if it is an unsupported iocb
* LPFC_SOL_IOCB if it is a solicited iocb completion
* LPFC_ABORT_IOCB if it is an abort iocb
* LPFC_UNSOL_IOCB if it is an unsolicited iocb
*
* The caller is not required to hold any lock.
**/
static lpfc_iocb_type static lpfc_iocb_type
lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd) lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd)
{ {
...@@ -230,6 +293,17 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd) ...@@ -230,6 +293,17 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd)
return type; return type;
} }
/**
* lpfc_sli_ring_map: Issue config_ring mbox for all rings.
* @phba: Pointer to HBA context object.
*
* This function is called from SLI initialization code
* to configure every ring of the HBA's SLI interface. The
* caller is not required to hold any lock. This function issues
* a config_ring mailbox command for each ring.
* This function returns zero if successful else returns a negative
* error code.
**/
static int static int
lpfc_sli_ring_map(struct lpfc_hba *phba) lpfc_sli_ring_map(struct lpfc_hba *phba)
{ {
...@@ -262,6 +336,18 @@ lpfc_sli_ring_map(struct lpfc_hba *phba) ...@@ -262,6 +336,18 @@ lpfc_sli_ring_map(struct lpfc_hba *phba)
return ret; return ret;
} }
/**
* lpfc_sli_ringtxcmpl_put: Adds new iocb to the txcmplq.
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @piocb: Pointer to the driver iocb object.
*
* This function is called with hbalock held. The function adds the
* new iocb to txcmplq of the given ring. This function always returns
* 0. If this function is called for ELS ring, this function checks if
* there is a vport associated with the ELS command. This function also
* starts els_tmofunc timer if this is an ELS command.
**/
static int static int
lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *piocb) struct lpfc_iocbq *piocb)
...@@ -282,6 +368,16 @@ lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -282,6 +368,16 @@ lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
return 0; return 0;
} }
/**
* lpfc_sli_ringtx_get: Get first element of the txq.
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
* This function is called with hbalock held to get next
* iocb in txq of the given ring. If there is any iocb in
* the txq, the function returns first iocb in the list after
* removing the iocb from the list, else it returns NULL.
**/
static struct lpfc_iocbq * static struct lpfc_iocbq *
lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{ {
...@@ -293,6 +389,20 @@ lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) ...@@ -293,6 +389,20 @@ lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
return cmd_iocb; return cmd_iocb;
} }
/**
* lpfc_sli_next_iocb_slot: Get next iocb slot in the ring.
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
* This function is called with hbalock held and the caller must post the
* iocb without releasing the lock. If the caller releases the lock,
* iocb slot returned by the function is not guaranteed to be available.
* The function returns pointer to the next available iocb slot if there
* is available slot in the ring, else it returns NULL.
* If the get index of the ring is ahead of the put index, the function
* will post an error attention event to the worker thread to take the
* HBA to offline state.
**/
static IOCB_t * static IOCB_t *
lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring) lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{ {
...@@ -336,6 +446,18 @@ lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring) ...@@ -336,6 +446,18 @@ lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
return lpfc_cmd_iocb(phba, pring); return lpfc_cmd_iocb(phba, pring);
} }
/**
* lpfc_sli_next_iotag: Get an iotag for the iocb.
* @phba: Pointer to HBA context object.
* @iocbq: Pointer to driver iocb object.
*
* This function gets an iotag for the iocb. If there is no unused iotag and
* the iocbq_lookup_len < 0xffff, this function allocates a bigger iotag_lookup
* array and assigns a new iotag.
* The function returns the allocated iotag if successful, else returns zero.
* Zero is not a valid iotag.
* The caller is not required to hold any lock.
**/
uint16_t uint16_t
lpfc_sli_next_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) lpfc_sli_next_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
{ {
...@@ -399,6 +521,20 @@ lpfc_sli_next_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) ...@@ -399,6 +521,20 @@ lpfc_sli_next_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
return 0; return 0;
} }
/**
* lpfc_sli_submit_iocb: Submit an iocb to the firmware.
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @iocb: Pointer to iocb slot in the ring.
* @nextiocb: Pointer to driver iocb object which need to be
* posted to firmware.
*
* This function is called with hbalock held to post a new iocb to
* the firmware. This function copies the new iocb to ring iocb slot and
* updates the ring pointers. It adds the new iocb to txcmplq if there is
* a completion call back for this iocb else the function will free the
* iocb object.
**/
static void static void
lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
IOCB_t *iocb, struct lpfc_iocbq *nextiocb) IOCB_t *iocb, struct lpfc_iocbq *nextiocb)
...@@ -441,6 +577,18 @@ lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -441,6 +577,18 @@ lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
writel(pring->cmdidx, &phba->host_gp[pring->ringno].cmdPutInx); writel(pring->cmdidx, &phba->host_gp[pring->ringno].cmdPutInx);
} }
/**
* lpfc_sli_update_full_ring: Update the chip attention register.
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
* The caller is not required to hold any lock for calling this function.
* This function updates the chip attention bits for the ring to inform firmware
* that there are pending work to be done for this ring and requests an
* interrupt when there is space available in the ring. This function is
* called when the driver is unable to post more iocbs to the ring due
* to unavailability of space in the ring.
**/
static void static void
lpfc_sli_update_full_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) lpfc_sli_update_full_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{ {
...@@ -460,6 +608,15 @@ lpfc_sli_update_full_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) ...@@ -460,6 +608,15 @@ lpfc_sli_update_full_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
pring->stats.iocb_cmd_full++; pring->stats.iocb_cmd_full++;
} }
/**
* lpfc_sli_update_ring: Update chip attention register.
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
* This function updates the chip attention register bit for the
* given ring to inform HBA that there is more work to be done
* in this ring. The caller is not required to hold any lock.
**/
static void static void
lpfc_sli_update_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) lpfc_sli_update_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{ {
...@@ -473,6 +630,15 @@ lpfc_sli_update_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) ...@@ -473,6 +630,15 @@ lpfc_sli_update_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
readl(phba->CAregaddr); /* flush */ readl(phba->CAregaddr); /* flush */
} }
/**
* lpfc_sli_resume_iocb: Process iocbs in the txq.
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
* This function is called with hbalock held to post pending iocbs
* in the txq to the firmware. This function is called when driver
* detects space available in the ring.
**/
static void static void
lpfc_sli_resume_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) lpfc_sli_resume_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{ {
...@@ -504,6 +670,16 @@ lpfc_sli_resume_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) ...@@ -504,6 +670,16 @@ lpfc_sli_resume_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
return; return;
} }
/**
* lpfc_sli_next_hbq_slot: Get next hbq entry for the HBQ.
* @phba: Pointer to HBA context object.
* @hbqno: HBQ number.
*
* This function is called with hbalock held to get the next
* available slot for the given HBQ. If there is free slot
* available for the HBQ it will return pointer to the next available
* HBQ entry else it will return NULL.
**/
static struct lpfc_hbq_entry * static struct lpfc_hbq_entry *
lpfc_sli_next_hbq_slot(struct lpfc_hba *phba, uint32_t hbqno) lpfc_sli_next_hbq_slot(struct lpfc_hba *phba, uint32_t hbqno)
{ {
...@@ -539,6 +715,15 @@ lpfc_sli_next_hbq_slot(struct lpfc_hba *phba, uint32_t hbqno) ...@@ -539,6 +715,15 @@ lpfc_sli_next_hbq_slot(struct lpfc_hba *phba, uint32_t hbqno)
hbqp->hbqPutIdx; hbqp->hbqPutIdx;
} }
/**
* lpfc_sli_hbqbuf_free_all: Free all the hbq buffers.
* @phba: Pointer to HBA context object.
*
* This function is called with no lock held to free all the
* hbq buffers while uninitializing the SLI interface. It also
* frees the HBQ buffers returned by the firmware but not yet
* processed by the upper layers.
**/
void void
lpfc_sli_hbqbuf_free_all(struct lpfc_hba *phba) lpfc_sli_hbqbuf_free_all(struct lpfc_hba *phba)
{ {
...@@ -584,6 +769,18 @@ lpfc_sli_hbqbuf_free_all(struct lpfc_hba *phba) ...@@ -584,6 +769,18 @@ lpfc_sli_hbqbuf_free_all(struct lpfc_hba *phba)
spin_unlock_irqrestore(&phba->hbalock, flags); spin_unlock_irqrestore(&phba->hbalock, flags);
} }
/**
* lpfc_sli_hbq_to_firmware: Post the hbq buffer to firmware.
* @phba: Pointer to HBA context object.
* @hbqno: HBQ number.
* @hbq_buf: Pointer to HBQ buffer.
*
* This function is called with the hbalock held to post a
* hbq buffer to the firmware. If the function finds an empty
* slot in the HBQ, it will post the buffer. The function will return
* pointer to the hbq entry if it successfully post the buffer
* else it will return NULL.
**/
static struct lpfc_hbq_entry * static struct lpfc_hbq_entry *
lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno, lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno,
struct hbq_dmabuf *hbq_buf) struct hbq_dmabuf *hbq_buf)
...@@ -612,6 +809,7 @@ lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno, ...@@ -612,6 +809,7 @@ lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno,
return hbqe; return hbqe;
} }
/* HBQ for ELS and CT traffic. */
static struct lpfc_hbq_init lpfc_els_hbq = { static struct lpfc_hbq_init lpfc_els_hbq = {
.rn = 1, .rn = 1,
.entry_count = 200, .entry_count = 200,
...@@ -623,6 +821,7 @@ static struct lpfc_hbq_init lpfc_els_hbq = { ...@@ -623,6 +821,7 @@ static struct lpfc_hbq_init lpfc_els_hbq = {
.add_count = 5, .add_count = 5,
}; };
/* HBQ for the extra ring if needed */
static struct lpfc_hbq_init lpfc_extra_hbq = { static struct lpfc_hbq_init lpfc_extra_hbq = {
.rn = 1, .rn = 1,
.entry_count = 200, .entry_count = 200,
...@@ -634,11 +833,22 @@ static struct lpfc_hbq_init lpfc_extra_hbq = { ...@@ -634,11 +833,22 @@ static struct lpfc_hbq_init lpfc_extra_hbq = {
.add_count = 5, .add_count = 5,
}; };
/* Array of HBQs */
struct lpfc_hbq_init *lpfc_hbq_defs[] = { struct lpfc_hbq_init *lpfc_hbq_defs[] = {
&lpfc_els_hbq, &lpfc_els_hbq,
&lpfc_extra_hbq, &lpfc_extra_hbq,
}; };
/**
* lpfc_sli_hbqbuf_fill_hbqs: Post more hbq buffers to HBQ.
* @phba: Pointer to HBA context object.
* @hbqno: HBQ number.
* @count: Number of HBQ buffers to be posted.
*
* This function is called with no lock held to post more
* hbq buffers to the given HBQ. The function returns 0
* when successful and returns 1 other wise.
**/
static int static int
lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count) lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count)
{ {
...@@ -679,6 +889,15 @@ lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count) ...@@ -679,6 +889,15 @@ lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count)
return 1; return 1;
} }
/**
* lpfc_sli_hbqbuf_add_hbqs: Post more HBQ buffers to firmware.
* @phba: Pointer to HBA context object.
* @qno: HBQ number.
*
* This function posts more buffers to the HBQ. This function
* is called with no lock held. The function returns 0 when
* successful and returns 1 otherwise.
**/
int int
lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *phba, uint32_t qno) lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *phba, uint32_t qno)
{ {
...@@ -686,6 +905,15 @@ lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *phba, uint32_t qno) ...@@ -686,6 +905,15 @@ lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *phba, uint32_t qno)
lpfc_hbq_defs[qno]->add_count)); lpfc_hbq_defs[qno]->add_count));
} }
/**
* lpfc_sli_hbqbuf_init_hbqs: Post initial buffers to the HBQ.
* @phba: Pointer to HBA context object.
* @qno: HBQ queue number.
*
* This function is called from SLI initialization code path with
* no lock held to post initial HBQ buffers to firmware. The
* function returns 0 when successful and returns 1 otherwise.
**/
static int static int
lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *phba, uint32_t qno) lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *phba, uint32_t qno)
{ {
...@@ -693,6 +921,16 @@ lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *phba, uint32_t qno) ...@@ -693,6 +921,16 @@ lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *phba, uint32_t qno)
lpfc_hbq_defs[qno]->init_count)); lpfc_hbq_defs[qno]->init_count));
} }
/**
* lpfc_sli_hbqbuf_find: Find the hbq buffer associated with a tag.
* @phba: Pointer to HBA context object.
* @tag: Tag of the hbq buffer.
*
* This function is called with hbalock held. This function searches
* for the hbq buffer associated with the given tag in the hbq buffer
* list. If it finds the hbq buffer, it returns the hbq_buffer other wise
* it returns NULL.
**/
static struct hbq_dmabuf * static struct hbq_dmabuf *
lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag) lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag)
{ {
...@@ -716,6 +954,15 @@ lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag) ...@@ -716,6 +954,15 @@ lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag)
return NULL; return NULL;
} }
/**
* lpfc_sli_free_hbq: Give back the hbq buffer to firmware.
* @phba: Pointer to HBA context object.
* @hbq_buffer: Pointer to HBQ buffer.
*
* This function is called with hbalock. This function gives back
* the hbq buffer to firmware. If the HBQ does not have space to
* post the buffer, it will free the buffer.
**/
void void
lpfc_sli_free_hbq(struct lpfc_hba *phba, struct hbq_dmabuf *hbq_buffer) lpfc_sli_free_hbq(struct lpfc_hba *phba, struct hbq_dmabuf *hbq_buffer)
{ {
...@@ -729,6 +976,15 @@ lpfc_sli_free_hbq(struct lpfc_hba *phba, struct hbq_dmabuf *hbq_buffer) ...@@ -729,6 +976,15 @@ lpfc_sli_free_hbq(struct lpfc_hba *phba, struct hbq_dmabuf *hbq_buffer)
} }
} }
/**
* lpfc_sli_chk_mbx_command: Check if the mailbox is a legitimate mailbox.
* @mbxCommand: mailbox command code.
*
* This function is called by the mailbox event handler function to verify
* that the completed mailbox command is a legitimate mailbox command. If the
* completed mailbox is not known to the function, it will return MBX_SHUTDOWN
* and the mailbox event handler will take the HBA offline.
**/
static int static int
lpfc_sli_chk_mbx_command(uint8_t mbxCommand) lpfc_sli_chk_mbx_command(uint8_t mbxCommand)
{ {
...@@ -793,6 +1049,19 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand) ...@@ -793,6 +1049,19 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand)
} }
return ret; return ret;
} }
/**
* lpfc_sli_wake_mbox_wait: Completion handler for mbox issued from
* lpfc_sli_issue_mbox_wait.
* @phba: Pointer to HBA context object.
* @pmboxq: Pointer to mailbox command.
*
* This is completion handler function for mailbox commands issued from
* lpfc_sli_issue_mbox_wait function. This function is called by the
* mailbox event handler function with no lock held. This function
* will wake up thread waiting on the wait queue pointed by context1
* of the mailbox.
**/
static void static void
lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
{ {
...@@ -812,6 +1081,17 @@ lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) ...@@ -812,6 +1081,17 @@ lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
return; return;
} }
/**
* lpfc_sli_def_mbox_cmpl: Default mailbox completion handler.
* @phba: Pointer to HBA context object.
* @pmb: Pointer to mailbox object.
*
* This function is the default mailbox completion handler. It
* frees the memory resources associated with the completed mailbox
* command. If the completed command is a REG_LOGIN mailbox command,
* this function will issue a UREG_LOGIN to re-claim the RPI.
**/
void void
lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{ {
...@@ -846,6 +1126,19 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -846,6 +1126,19 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
return; return;
} }
/**
* lpfc_sli_handle_mb_event: Handle mailbox completions from firmware.
* @phba: Pointer to HBA context object.
*
* This function is called with no lock held. This function processes all
* the completed mailbox commands and gives it to upper layers. The interrupt
* service routine processes mailbox completion interrupt and adds completed
* mailbox commands to the mboxq_cmpl queue and signals the worker thread.
* Worker thread call lpfc_sli_handle_mb_event, which will return the
* completed mailbox commands in mboxq_cmpl queue to the upper layers. This
* function returns the mailbox commands to the upper layer by calling the
* completion handler function of each mailbox.
**/
int int
lpfc_sli_handle_mb_event(struct lpfc_hba *phba) lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
{ {
...@@ -953,6 +1246,16 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba) ...@@ -953,6 +1246,16 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
return 0; return 0;
} }
/**
* lpfc_sli_replace_hbqbuff: Replace the HBQ buffer with a new buffer.
* @phba: Pointer to HBA context object.
* @tag: Tag for the HBQ buffer.
*
* This function is called from unsolicited event handler code path to get the
* HBQ buffer associated with an unsolicited iocb. This function is called with
* no lock held. It returns the buffer associated with the given tag and posts
* another buffer to the firmware.
**/
static struct lpfc_dmabuf * static struct lpfc_dmabuf *
lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag) lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag)
{ {
...@@ -997,6 +1300,18 @@ lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag) ...@@ -997,6 +1300,18 @@ lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag)
return &new_hbq_entry->dbuf; return &new_hbq_entry->dbuf;
} }
/**
* lpfc_sli_get_buff: Get the buffer associated with the buffer tag.
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @tag: buffer tag.
*
* This function is called with no lock held. When QUE_BUFTAG_BIT bit
* is set in the tag the buffer is posted for a particular exchange,
* the function will return the buffer without replacing the buffer.
* If the buffer is for unsolicited ELS or CT traffic, this function
* returns the buffer and also posts another buffer to the firmware.
**/
static struct lpfc_dmabuf * static struct lpfc_dmabuf *
lpfc_sli_get_buff(struct lpfc_hba *phba, lpfc_sli_get_buff(struct lpfc_hba *phba,
struct lpfc_sli_ring *pring, struct lpfc_sli_ring *pring,
...@@ -1008,6 +1323,21 @@ lpfc_sli_get_buff(struct lpfc_hba *phba, ...@@ -1008,6 +1323,21 @@ lpfc_sli_get_buff(struct lpfc_hba *phba,
return lpfc_sli_replace_hbqbuff(phba, tag); return lpfc_sli_replace_hbqbuff(phba, tag);
} }
/**
* lpfc_sli_process_unsol_iocb: Unsolicited iocb handler.
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @saveq: Pointer to the unsolicited iocb.
*
* This function is called with no lock held by the ring event handler
* when there is an unsolicited iocb posted to the response ring by the
* firmware. This function gets the buffer associated with the iocbs
* and calls the event handler for the ring. This function handles both
* qring buffers and hbq buffers.
* When the function returns 1 the caller can free the iocb object otherwise
* upper layer functions will free the iocb objects.
**/
static int static int
lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *saveq) struct lpfc_iocbq *saveq)
...@@ -1192,6 +1522,18 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -1192,6 +1522,18 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
return 1; return 1;
} }
/**
* lpfc_sli_iocbq_lookup: Find command iocb for the given response iocb.
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @prspiocb: Pointer to response iocb object.
*
* This function looks up the iocb_lookup table to get the command iocb
* corresponding to the given response iocb using the iotag of the
* response iocb. This function is called with the hbalock held.
* This function returns the command iocb object if it finds the command
* iocb else returns NULL.
**/
static struct lpfc_iocbq * static struct lpfc_iocbq *
lpfc_sli_iocbq_lookup(struct lpfc_hba *phba, lpfc_sli_iocbq_lookup(struct lpfc_hba *phba,
struct lpfc_sli_ring *pring, struct lpfc_sli_ring *pring,
...@@ -1217,6 +1559,23 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *phba, ...@@ -1217,6 +1559,23 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *phba,
return NULL; return NULL;
} }
/**
* lpfc_sli_process_sol_iocb: process solicited iocb completion.
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @saveq: Pointer to the response iocb to be processed.
*
* This function is called by the ring event handler for non-fcp
* rings when there is a new response iocb in the response ring.
* The caller is not required to hold any locks. This function
* gets the command iocb associated with the response iocb and
* calls the completion handler for the command iocb. If there
* is no completion handler, the function will free the resources
* associated with command iocb. If the response iocb is for
* an already aborted command iocb, the status of the completion
* is changed to IOSTAT_LOCAL_REJECT/IOERR_SLI_ABORTED.
* This function always returns 1.
**/
static int static int
lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *saveq) struct lpfc_iocbq *saveq)
...@@ -1282,6 +1641,16 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -1282,6 +1641,16 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
return rc; return rc;
} }
/**
* lpfc_sli_rsp_pointers_error: Response ring pointer error handler.
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
* This function is called from the iocb ring event handlers when
* put pointer is ahead of the get pointer for a ring. This function signal
* an error attention condition to the worker thread and the worker
* thread will transition the HBA to offline state.
**/
static void static void
lpfc_sli_rsp_pointers_error(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) lpfc_sli_rsp_pointers_error(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{ {
...@@ -1312,6 +1681,21 @@ lpfc_sli_rsp_pointers_error(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) ...@@ -1312,6 +1681,21 @@ lpfc_sli_rsp_pointers_error(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
return; return;
} }
/**
* lpfc_sli_poll_fcp_ring: Handle FCP ring completion in polling mode.
* @phba: Pointer to HBA context object.
*
* This function is called from lpfc_queuecommand, lpfc_poll_timeout,
* lpfc_abort_handler and lpfc_slave_configure when FCP_RING_POLLING
* is enabled.
*
* The caller does not hold any lock.
* The function processes each response iocb in the response ring until it
* finds an iocb with LE bit set and chains all the iocbs upto the iocb with
* LE bit set. The function will call the completion handler of the command iocb
* if the response iocb indicates a completion for a command iocb or it is
* an abort completion.
**/
void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba) void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba)
{ {
struct lpfc_sli *psli = &phba->sli; struct lpfc_sli *psli = &phba->sli;
...@@ -1465,10 +1849,23 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba) ...@@ -1465,10 +1849,23 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba)
return; return;
} }
/* /**
* lpfc_sli_handle_fast_ring_event: Handle ring events on FCP ring.
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @mask: Host attention register mask for this ring.
*
* This function is called from the interrupt context when there is a ring
* event for the fcp ring. The caller does not hold any lock.
* The function processes each response iocb in the response ring until it
* finds an iocb with LE bit set and chains all the iocbs upto the iocb with
* LE bit set. The function will call the completion handler of the command iocb
* if the response iocb indicates a completion for a command iocb or it is
* an abort completion. The function will call lpfc_sli_process_unsol_iocb
* function if this is an unsolicited iocb.
* This routine presumes LPFC_FCP_RING handling and doesn't bother * This routine presumes LPFC_FCP_RING handling and doesn't bother
* to check it explicitly. * to check it explicitly. This function always returns 1.
*/ **/
static int static int
lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba, lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba,
struct lpfc_sli_ring *pring, uint32_t mask) struct lpfc_sli_ring *pring, uint32_t mask)
...@@ -1646,6 +2043,23 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba, ...@@ -1646,6 +2043,23 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba,
return rc; return rc;
} }
/**
* lpfc_sli_handle_slow_ring_event: Handle ring events for non-FCP rings.
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @mask: Host attention register mask for this ring.
*
* This function is called from the worker thread when there is a ring
* event for non-fcp rings. The caller does not hold any lock .
* The function processes each response iocb in the response ring until it
* finds an iocb with LE bit set and chains all the iocbs upto the iocb with
* LE bit set. The function will call lpfc_sli_process_sol_iocb function if the
* response iocb indicates a completion of a command iocb. The function
* will call lpfc_sli_process_unsol_iocb function if this is an unsolicited
* iocb. The function frees the resources or calls the completion handler if
* this iocb is an abort completion. The function returns 0 when the allocated
* iocbs are not freed, otherwise returns 1.
**/
int int
lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba, lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
struct lpfc_sli_ring *pring, uint32_t mask) struct lpfc_sli_ring *pring, uint32_t mask)
...@@ -1904,6 +2318,16 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba, ...@@ -1904,6 +2318,16 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
return rc; return rc;
} }
/**
* lpfc_sli_abort_iocb_ring: Abort all iocbs in the ring.
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
* This function aborts all iocbs in the given ring and frees all the iocb
* objects in txq. This function issues an abort iocb for all the iocb commands
* in txcmplq. The iocbs in the txcmplq is not guaranteed to complete before
* the return of this function. The caller is not required to hold any locks.
**/
void void
lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{ {
...@@ -1943,6 +2367,19 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) ...@@ -1943,6 +2367,19 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
} }
} }
/**
* lpfc_sli_brdready: Check for host status bits.
* @phba: Pointer to HBA context object.
* @mask: Bit mask to be checked.
*
* This function reads the host status register and compares
* with the provided bit mask to check if HBA completed
* the restart. This function will wait in a loop for the
* HBA to complete restart. If the HBA does not restart within
* 15 iterations, the function will reset the HBA again. The
* function returns 1 when HBA fail to restart otherwise returns
* zero.
**/
int int
lpfc_sli_brdready(struct lpfc_hba *phba, uint32_t mask) lpfc_sli_brdready(struct lpfc_hba *phba, uint32_t mask)
{ {
...@@ -1990,6 +2427,13 @@ lpfc_sli_brdready(struct lpfc_hba *phba, uint32_t mask) ...@@ -1990,6 +2427,13 @@ lpfc_sli_brdready(struct lpfc_hba *phba, uint32_t mask)
#define BARRIER_TEST_PATTERN (0xdeadbeef) #define BARRIER_TEST_PATTERN (0xdeadbeef)
/**
* lpfc_reset_barrier: Make HBA ready for HBA reset.
* @phba: Pointer to HBA context object.
*
* This function is called before resetting an HBA. This
* function requests HBA to quiesce DMAs before a reset.
**/
void lpfc_reset_barrier(struct lpfc_hba *phba) void lpfc_reset_barrier(struct lpfc_hba *phba)
{ {
uint32_t __iomem *resp_buf; uint32_t __iomem *resp_buf;
...@@ -2063,6 +2507,17 @@ restore_hc: ...@@ -2063,6 +2507,17 @@ restore_hc:
readl(phba->HCregaddr); /* flush */ readl(phba->HCregaddr); /* flush */
} }
/**
* lpfc_sli_brdkill: Issue a kill_board mailbox command.
* @phba: Pointer to HBA context object.
*
* This function issues a kill_board mailbox command and waits for
* the error attention interrupt. This function is called for stopping
* the firmware processing. The caller is not required to hold any
* locks. This function calls lpfc_hba_down_post function to free
* any pending commands after the kill. The function will return 1 when it
* fails to kill the board else will return 0.
**/
int int
lpfc_sli_brdkill(struct lpfc_hba *phba) lpfc_sli_brdkill(struct lpfc_hba *phba)
{ {
...@@ -2139,6 +2594,17 @@ lpfc_sli_brdkill(struct lpfc_hba *phba) ...@@ -2139,6 +2594,17 @@ lpfc_sli_brdkill(struct lpfc_hba *phba)
return ha_copy & HA_ERATT ? 0 : 1; return ha_copy & HA_ERATT ? 0 : 1;
} }
/**
* lpfc_sli_brdreset: Reset the HBA.
* @phba: Pointer to HBA context object.
*
* This function resets the HBA by writing HC_INITFF to the control
* register. After the HBA resets, this function resets all the iocb ring
* indices. This function disables PCI layer parity checking during
* the reset.
* This function returns 0 always.
* The caller is not required to hold any locks.
**/
int int
lpfc_sli_brdreset(struct lpfc_hba *phba) lpfc_sli_brdreset(struct lpfc_hba *phba)
{ {
...@@ -2191,6 +2657,19 @@ lpfc_sli_brdreset(struct lpfc_hba *phba) ...@@ -2191,6 +2657,19 @@ lpfc_sli_brdreset(struct lpfc_hba *phba)
return 0; return 0;
} }
/**
* lpfc_sli_brdrestart: Restart the HBA.
* @phba: Pointer to HBA context object.
*
* This function is called in the SLI initialization code path to
* restart the HBA. The caller is not required to hold any lock.
* This function writes MBX_RESTART mailbox command to the SLIM and
* resets the HBA. At the end of the function, it calls lpfc_hba_down_post
* function to free any pending commands. The function enables
* POST only during the first initialization. The function returns zero.
* The function does not guarantee completion of MBX_RESTART mailbox
* command before the return of this function.
**/
int int
lpfc_sli_brdrestart(struct lpfc_hba *phba) lpfc_sli_brdrestart(struct lpfc_hba *phba)
{ {
...@@ -2251,6 +2730,16 @@ lpfc_sli_brdrestart(struct lpfc_hba *phba) ...@@ -2251,6 +2730,16 @@ lpfc_sli_brdrestart(struct lpfc_hba *phba)
return 0; return 0;
} }
/**
* lpfc_sli_chipset_init: Wait for the restart of the HBA after a restart.
* @phba: Pointer to HBA context object.
*
* This function is called after a HBA restart to wait for successful
* restart of the HBA. Successful restart of the HBA is indicated by
* HS_FFRDY and HS_MBRDY bits. If the HBA fails to restart even after 15
* iteration, the function will restart the HBA again. The function returns
* zero if HBA successfully restarted else returns negative error code.
**/
static int static int
lpfc_sli_chipset_init(struct lpfc_hba *phba) lpfc_sli_chipset_init(struct lpfc_hba *phba)
{ {
...@@ -2336,12 +2825,25 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba) ...@@ -2336,12 +2825,25 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
return 0; return 0;
} }
/**
* lpfc_sli_hbq_count: Get the number of HBQs to be configured.
*
* This function calculates and returns the number of HBQs required to be
* configured.
**/
int int
lpfc_sli_hbq_count(void) lpfc_sli_hbq_count(void)
{ {
return ARRAY_SIZE(lpfc_hbq_defs); return ARRAY_SIZE(lpfc_hbq_defs);
} }
/**
* lpfc_sli_hbq_entry_count: Calculate total number of hbq entries.
*
* This function adds the number of hbq entries in every HBQ to get
* the total number of hbq entries required for the HBA and returns
* the total count.
**/
static int static int
lpfc_sli_hbq_entry_count(void) lpfc_sli_hbq_entry_count(void)
{ {
...@@ -2354,12 +2856,27 @@ lpfc_sli_hbq_entry_count(void) ...@@ -2354,12 +2856,27 @@ lpfc_sli_hbq_entry_count(void)
return count; return count;
} }
/**
* lpfc_sli_hbq_size: Calculate memory required for all hbq entries.
*
* This function calculates amount of memory required for all hbq entries
* to be configured and returns the total memory required.
**/
int int
lpfc_sli_hbq_size(void) lpfc_sli_hbq_size(void)
{ {
return lpfc_sli_hbq_entry_count() * sizeof(struct lpfc_hbq_entry); return lpfc_sli_hbq_entry_count() * sizeof(struct lpfc_hbq_entry);
} }
/**
* lpfc_sli_hbq_setup: configure and initialize HBQs.
* @phba: Pointer to HBA context object.
*
* This function is called during the SLI initialization to configure
* all the HBQs and post buffers to the HBQ. The caller is not
* required to hold any locks. This function will return zero if successful
* else it will return negative error code.
**/
static int static int
lpfc_sli_hbq_setup(struct lpfc_hba *phba) lpfc_sli_hbq_setup(struct lpfc_hba *phba)
{ {
...@@ -2422,6 +2939,19 @@ lpfc_sli_hbq_setup(struct lpfc_hba *phba) ...@@ -2422,6 +2939,19 @@ lpfc_sli_hbq_setup(struct lpfc_hba *phba)
return 0; return 0;
} }
/**
* lpfc_do_config_port: Issue config port mailbox command.
* @phba: Pointer to HBA context object.
* @sli_mode: sli mode - 2/3
*
* This function is called by the sli intialization code path
* to issue config_port mailbox command. This function restarts the
* HBA firmware and issues a config_port mailbox command to configure
* the SLI interface in the sli mode specified by sli_mode
* variable. The caller is not required to hold any locks.
* The function returns 0 if successful, else returns negative error
* code.
**/
static int static int
lpfc_do_config_port(struct lpfc_hba *phba, int sli_mode) lpfc_do_config_port(struct lpfc_hba *phba, int sli_mode)
{ {
...@@ -2500,6 +3030,20 @@ do_prep_failed: ...@@ -2500,6 +3030,20 @@ do_prep_failed:
return rc; return rc;
} }
/**
* lpfc_sli_hba_setup: SLI intialization function.
* @phba: Pointer to HBA context object.
*
* This function is the main SLI intialization function. This function
* is called by the HBA intialization code, HBA reset code and HBA
* error attention handler code. Caller is not required to hold any
* locks. This function issues config_port mailbox command to configure
* the SLI, setup iocb rings and HBQ rings. In the end the function
* calls the config_port_post function to issue init_link mailbox
* command and to start the discovery. The function will return zero
* if successful, else it will return negative error code.
**/
int int
lpfc_sli_hba_setup(struct lpfc_hba *phba) lpfc_sli_hba_setup(struct lpfc_hba *phba)
{ {
...@@ -2581,19 +3125,19 @@ lpfc_sli_hba_setup_error: ...@@ -2581,19 +3125,19 @@ lpfc_sli_hba_setup_error:
return rc; return rc;
} }
/*! lpfc_mbox_timeout
* /**
* \pre * lpfc_mbox_timeout: Timeout call back function for mbox timer.
* \post * @ptr: context object - pointer to hba structure.
* \param hba Pointer to per struct lpfc_hba structure
* \param l1 Pointer to the driver's mailbox queue.
* \return
* void
*
* \b Description:
* *
* This routine handles mailbox timeout events at timer interrupt context. * This is the callback function for mailbox timer. The mailbox
*/ * timer is armed when a new mailbox command is issued and the timer
* is deleted when the mailbox complete. The function is called by
* the kernel timer code when a mailbox does not complete within
* expected time. This function wakes up the worker thread to
* process the mailbox timeout and returns. All the processing is
* done by the worker thread function lpfc_mbox_timeout_handler.
**/
void void
lpfc_mbox_timeout(unsigned long ptr) lpfc_mbox_timeout(unsigned long ptr)
{ {
...@@ -2612,6 +3156,15 @@ lpfc_mbox_timeout(unsigned long ptr) ...@@ -2612,6 +3156,15 @@ lpfc_mbox_timeout(unsigned long ptr)
return; return;
} }
/**
* lpfc_mbox_timeout_handler: Worker thread function to handle mailbox timeout.
* @phba: Pointer to HBA context object.
*
* This function is called from worker thread when a mailbox command times out.
* The caller is not required to hold any locks. This function will reset the
* HBA and recover all the pending commands.
**/
void void
lpfc_mbox_timeout_handler(struct lpfc_hba *phba) lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
{ {
...@@ -2666,6 +3219,32 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba) ...@@ -2666,6 +3219,32 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
return; return;
} }
/**
* lpfc_sli_issue_mbox: Issue a mailbox command to firmware.
* @phba: Pointer to HBA context object.
* @pmbox: Pointer to mailbox object.
* @flag: Flag indicating how the mailbox need to be processed.
*
* This function is called by discovery code and HBA management code
* to submit a mailbox command to firmware. This function gets the
* hbalock to protect the data structures.
* The mailbox command can be submitted in polling mode, in which case
* this function will wait in a polling loop for the completion of the
* mailbox.
* If the mailbox is submitted in no_wait mode (not polling) the
* function will submit the command and returns immediately without waiting
* for the mailbox completion. The no_wait is supported only when HBA
* is in SLI2/SLI3 mode - interrupts are enabled.
* The SLI interface allows only one mailbox pending at a time. If the
* mailbox is issued in polling mode and there is already a mailbox
* pending, then the function will return an error. If the mailbox is issued
* in NO_WAIT mode and there is a mailbox pending already, the function
* will return MBX_BUSY after queuing the mailbox into mailbox queue.
* The sli layer owns the mailbox object until the completion of mailbox
* command if this function return MBX_BUSY or MBX_SUCCESS. For all other
* return codes the caller owns the mailbox command after the return of
* the function.
**/
int int
lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
{ {
...@@ -2980,9 +3559,16 @@ out_not_finished: ...@@ -2980,9 +3559,16 @@ out_not_finished:
return MBX_NOT_FINISHED; return MBX_NOT_FINISHED;
} }
/* /**
* Caller needs to hold lock. * __lpfc_sli_ringtx_put: Add an iocb to the txq.
*/ * @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @piocb: Pointer to address of newly added command iocb.
*
* This function is called with hbalock held to add a command
* iocb to the txq when SLI layer cannot submit the command iocb
* to the ring.
**/
static void static void
__lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, __lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *piocb) struct lpfc_iocbq *piocb)
...@@ -2992,6 +3578,23 @@ __lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -2992,6 +3578,23 @@ __lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
pring->txq_cnt++; pring->txq_cnt++;
} }
/**
* lpfc_sli_next_iocb: Get the next iocb in the txq.
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @piocb: Pointer to address of newly added command iocb.
*
* This function is called with hbalock held before a new
* iocb is submitted to the firmware. This function checks
* txq to flush the iocbs in txq to Firmware before
* submitting new iocbs to the Firmware.
* If there are iocbs in the txq which need to be submitted
* to firmware, lpfc_sli_next_iocb returns the first element
* of the txq after dequeuing it from txq.
* If there is no iocb in the txq then the function will return
* *piocb and *piocb is set to NULL. Caller needs to check
* *piocb to find if there are more commands in the txq.
**/
static struct lpfc_iocbq * static struct lpfc_iocbq *
lpfc_sli_next_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, lpfc_sli_next_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq **piocb) struct lpfc_iocbq **piocb)
...@@ -3007,9 +3610,30 @@ lpfc_sli_next_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -3007,9 +3610,30 @@ lpfc_sli_next_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
return nextiocb; return nextiocb;
} }
/* /**
* Lockless version of lpfc_sli_issue_iocb. * __lpfc_sli_issue_iocb: Lockless version of lpfc_sli_issue_iocb.
*/ * @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @piocb: Pointer to command iocb.
* @flag: Flag indicating if this command can be put into txq.
*
* __lpfc_sli_issue_iocb is used by other functions in the driver
* to issue an iocb command to the HBA. If the PCI slot is recovering
* from error state or if HBA is resetting or if LPFC_STOP_IOCB_EVENT
* flag is turned on, the function returns IOCB_ERROR.
* When the link is down, this function allows only iocbs for
* posting buffers.
* This function finds next available slot in the command ring and
* posts the command to the available slot and writes the port
* attention register to request HBA start processing new iocb.
* If there is no slot available in the ring and
* flag & SLI_IOCB_RET_IOCB is set, the new iocb is added to the
* txq, otherwise the function returns IOCB_BUSY.
*
* This function is called with hbalock held.
* The function will return success after it successfully submit the
* iocb to firmware or after adding to the txq.
**/
static int static int
__lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, __lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *piocb, uint32_t flag) struct lpfc_iocbq *piocb, uint32_t flag)
...@@ -3106,6 +3730,19 @@ __lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -3106,6 +3730,19 @@ __lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
} }
/**
* lpfc_sli_issue_iocb: Wrapper function for __lpfc_sli_issue_iocb.
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @piocb: Pointer to command iocb.
* @flag: Flag indicating if this command can be put into txq.
*
* lpfc_sli_issue_iocb is a wrapper around __lpfc_sli_issue_iocb
* function. This function gets the hbalock and calls
* __lpfc_sli_issue_iocb function and will return the error returned
* by __lpfc_sli_issue_iocb function. This wrapper is used by
* functions which do not hold hbalock.
**/
int int
lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *piocb, uint32_t flag) struct lpfc_iocbq *piocb, uint32_t flag)
...@@ -3120,6 +3757,17 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -3120,6 +3757,17 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
return rc; return rc;
} }
/**
* lpfc_extra_ring_setup: Extra ring setup function.
* @phba: Pointer to HBA context object.
*
* This function is called while driver attaches with the
* HBA to setup the extra ring. The extra ring is used
* only when driver needs to support target mode functionality
* or IP over FC functionalities.
*
* This function is called with no lock held.
**/
static int static int
lpfc_extra_ring_setup( struct lpfc_hba *phba) lpfc_extra_ring_setup( struct lpfc_hba *phba)
{ {
...@@ -3155,6 +3803,19 @@ lpfc_extra_ring_setup( struct lpfc_hba *phba) ...@@ -3155,6 +3803,19 @@ lpfc_extra_ring_setup( struct lpfc_hba *phba)
return 0; return 0;
} }
/**
* lpfc_sli_async_event_handler: ASYNC iocb handler function.
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @iocbq: Pointer to iocb object.
*
* This function is called by the slow ring event handler
* function when there is an ASYNC event iocb in the ring.
* This function is called with no lock held.
* Currently this function handles only temperature related
* ASYNC events. The function decodes the temperature sensor
* event message and posts events for the management applications.
**/
static void static void
lpfc_sli_async_event_handler(struct lpfc_hba * phba, lpfc_sli_async_event_handler(struct lpfc_hba * phba,
struct lpfc_sli_ring * pring, struct lpfc_iocbq * iocbq) struct lpfc_sli_ring * pring, struct lpfc_iocbq * iocbq)
...@@ -3210,6 +3871,17 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba, ...@@ -3210,6 +3871,17 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba,
} }
/**
* lpfc_sli_setup: SLI ring setup function.
* @phba: Pointer to HBA context object.
*
* lpfc_sli_setup sets up rings of the SLI interface with
* number of iocbs per ring and iotags. This function is
* called while driver attach to the HBA and before the
* interrupts are enabled. So there is no need for locking.
*
* This function always returns 0.
**/
int int
lpfc_sli_setup(struct lpfc_hba *phba) lpfc_sli_setup(struct lpfc_hba *phba)
{ {
...@@ -3321,6 +3993,17 @@ lpfc_sli_setup(struct lpfc_hba *phba) ...@@ -3321,6 +3993,17 @@ lpfc_sli_setup(struct lpfc_hba *phba)
return 0; return 0;
} }
/**
* lpfc_sli_queue_setup: Queue initialization function.
* @phba: Pointer to HBA context object.
*
* lpfc_sli_queue_setup sets up mailbox queues and iocb queues for each
* ring. This function also initializes ring indices of each ring.
* This function is called during the initialization of the SLI
* interface of an HBA.
* This function is called with no lock held and always returns
* 1.
**/
int int
lpfc_sli_queue_setup(struct lpfc_hba *phba) lpfc_sli_queue_setup(struct lpfc_hba *phba)
{ {
...@@ -3349,6 +4032,23 @@ lpfc_sli_queue_setup(struct lpfc_hba *phba) ...@@ -3349,6 +4032,23 @@ lpfc_sli_queue_setup(struct lpfc_hba *phba)
return 1; return 1;
} }
/**
* lpfc_sli_host_down: Vport cleanup function.
* @vport: Pointer to virtual port object.
*
* lpfc_sli_host_down is called to clean up the resources
* associated with a vport before destroying virtual
* port data structures.
* This function does following operations:
* - Free discovery resources associated with this virtual
* port.
* - Free iocbs associated with this virtual port in
* the txq.
* - Send abort for all iocb commands associated with this
* vport in txcmplq.
*
* This function is called with no lock held and always returns 1.
**/
int int
lpfc_sli_host_down(struct lpfc_vport *vport) lpfc_sli_host_down(struct lpfc_vport *vport)
{ {
...@@ -3411,6 +4111,21 @@ lpfc_sli_host_down(struct lpfc_vport *vport) ...@@ -3411,6 +4111,21 @@ lpfc_sli_host_down(struct lpfc_vport *vport)
return 1; return 1;
} }
/**
* lpfc_sli_hba_down: Resource cleanup function for the HBA.
* @phba: Pointer to HBA context object.
*
* This function cleans up all iocb, buffers, mailbox commands
* while shutting down the HBA. This function is called with no
* lock held and always returns 1.
* This function does the following to cleanup driver resources:
* - Free discovery resources for each virtual port
* - Cleanup any pending fabric iocbs
* - Iterate through the iocb txq and free each entry
* in the list.
* - Free up any buffer posted to the HBA
* - Free mailbox commands in the mailbox queue.
**/
int int
lpfc_sli_hba_down(struct lpfc_hba *phba) lpfc_sli_hba_down(struct lpfc_hba *phba)
{ {
...@@ -3501,6 +4216,18 @@ lpfc_sli_hba_down(struct lpfc_hba *phba) ...@@ -3501,6 +4216,18 @@ lpfc_sli_hba_down(struct lpfc_hba *phba)
return 1; return 1;
} }
/**
* lpfc_sli_pcimem_bcopy: SLI memory copy function.
* @srcp: Source memory pointer.
* @destp: Destination memory pointer.
* @cnt: Number of words required to be copied.
*
* This function is used for copying data between driver memory
* and the SLI memory. This function also changes the endianness
* of each word if native endianness is different from SLI
* endianness. This function can be called with or without
* lock.
**/
void void
lpfc_sli_pcimem_bcopy(void *srcp, void *destp, uint32_t cnt) lpfc_sli_pcimem_bcopy(void *srcp, void *destp, uint32_t cnt)
{ {
...@@ -3518,6 +4245,17 @@ lpfc_sli_pcimem_bcopy(void *srcp, void *destp, uint32_t cnt) ...@@ -3518,6 +4245,17 @@ lpfc_sli_pcimem_bcopy(void *srcp, void *destp, uint32_t cnt)
} }
} }
/**
* lpfc_sli_ringpostbuf_put: Function to add a buffer to postbufq.
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @mp: Pointer to driver buffer object.
*
* This function is called with no lock held.
* It always return zero after adding the buffer to the postbufq
* buffer list.
**/
int int
lpfc_sli_ringpostbuf_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, lpfc_sli_ringpostbuf_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_dmabuf *mp) struct lpfc_dmabuf *mp)
...@@ -3531,6 +4269,18 @@ lpfc_sli_ringpostbuf_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -3531,6 +4269,18 @@ lpfc_sli_ringpostbuf_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
return 0; return 0;
} }
/**
* lpfc_sli_get_buffer_tag: Tag allocation function for a buffer posted
* using CMD_QUE_XRI64_CX iocb.
* @phba: Pointer to HBA context object.
*
* When HBQ is enabled, buffers are searched based on tags. This function
* allocates a tag for buffer posted using CMD_QUE_XRI64_CX iocb. The
* tag is bit wise or-ed with QUE_BUFTAG_BIT to make sure that the tag
* does not conflict with tags of buffer posted for unsolicited events.
* The function returns the allocated tag. The function is called with
* no locks held.
**/
uint32_t uint32_t
lpfc_sli_get_buffer_tag(struct lpfc_hba *phba) lpfc_sli_get_buffer_tag(struct lpfc_hba *phba)
{ {
...@@ -3545,6 +4295,22 @@ lpfc_sli_get_buffer_tag(struct lpfc_hba *phba) ...@@ -3545,6 +4295,22 @@ lpfc_sli_get_buffer_tag(struct lpfc_hba *phba)
return phba->buffer_tag_count; return phba->buffer_tag_count;
} }
/**
* lpfc_sli_ring_taggedbuf_get: Search HBQ buffer associated with
* posted using CMD_QUE_XRI64_CX iocb.
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @tag: Buffer tag.
*
* Buffers posted using CMD_QUE_XRI64_CX iocb are in pring->postbufq
* list. After HBA DMA data to these buffers, CMD_IOCB_RET_XRI64_CX
* iocb is posted to the response ring with the tag of the buffer.
* This function searches the pring->postbufq list using the tag
* to find buffer associated with CMD_IOCB_RET_XRI64_CX
* iocb. If the buffer is found then lpfc_dmabuf object of the
* buffer is returned to the caller else NULL is returned.
* This function is called with no lock held.
**/
struct lpfc_dmabuf * struct lpfc_dmabuf *
lpfc_sli_ring_taggedbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, lpfc_sli_ring_taggedbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
uint32_t tag) uint32_t tag)
...@@ -3573,6 +4339,23 @@ lpfc_sli_ring_taggedbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -3573,6 +4339,23 @@ lpfc_sli_ring_taggedbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
return NULL; return NULL;
} }
/**
* lpfc_sli_ringpostbuf_get: SLI2 buffer search function for
* unsolicited ct and els events.
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @phys: DMA address of the buffer.
*
* This function searches the buffer list using the dma_address
* of unsolicited event to find the driver's lpfc_dmabuf object
* corresponding to the dma_address. The function returns the
* lpfc_dmabuf object if a buffer is found else it returns NULL.
* This function is called by the ct and els unsolicited event
* handlers to get the buffer associated with the unsolicited
* event.
*
* This function is called with no lock held.
**/
struct lpfc_dmabuf * struct lpfc_dmabuf *
lpfc_sli_ringpostbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, lpfc_sli_ringpostbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
dma_addr_t phys) dma_addr_t phys)
...@@ -3600,6 +4383,17 @@ lpfc_sli_ringpostbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -3600,6 +4383,17 @@ lpfc_sli_ringpostbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
return NULL; return NULL;
} }
/**
* lpfc_sli_abort_els_cmpl: Completion handler for the els abort iocbs.
* @phba: Pointer to HBA context object.
* @cmdiocb: Pointer to driver command iocb object.
* @rspiocb: Pointer to driver response iocb object.
*
* This function is the completion handler for the abort iocbs for
* ELS commands. This function is called from the ELS ring event
* handler with no lock held. This function frees memory resources
* associated with the abort iocb.
**/
static void static void
lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb) struct lpfc_iocbq *rspiocb)
...@@ -3665,6 +4459,17 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -3665,6 +4459,17 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
return; return;
} }
/**
* lpfc_ignore_els_cmpl: Completion handler for aborted ELS command.
* @phba: Pointer to HBA context object.
* @cmdiocb: Pointer to driver command iocb object.
* @rspiocb: Pointer to driver response iocb object.
*
* The function is called from SLI ring event handler with no
* lock held. This function is the completion handler for ELS commands
* which are aborted. The function frees memory resources used for
* the aborted ELS commands.
**/
static void static void
lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb) struct lpfc_iocbq *rspiocb)
...@@ -3684,6 +4489,17 @@ lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -3684,6 +4489,17 @@ lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
return; return;
} }
/**
* lpfc_sli_issue_abort_iotag: Abort function for a command iocb.
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @cmdiocb: Pointer to driver command iocb object.
*
* This function issues an abort iocb for the provided command
* iocb. This function is called with hbalock held.
* The function returns 0 when it fails due to memory allocation
* failure or when the command iocb is an abort request.
**/
int int
lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *cmdiocb) struct lpfc_iocbq *cmdiocb)
...@@ -3757,6 +4573,29 @@ abort_iotag_exit: ...@@ -3757,6 +4573,29 @@ abort_iotag_exit:
return retval; return retval;
} }
/**
* lpfc_sli_validate_fcp_iocb: Filtering function, used to find commands
* associated with a vport/SCSI target/lun.
* @iocbq: Pointer to driver iocb object.
* @vport: Pointer to driver virtual port object.
* @tgt_id: SCSI ID of the target.
* @lun_id: LUN ID of the scsi device.
* @ctx_cmd: LPFC_CTX_LUN/LPFC_CTX_TGT/LPFC_CTX_HOST
*
* This function acts as iocb filter for functions which abort or count
* all FCP iocbs pending on a lun/SCSI target/SCSI host. It will return
* 0 if the filtering criteria is met for the given iocb and will return
* 1 if the filtering criteria is not met.
* If ctx_cmd == LPFC_CTX_LUN, the function returns 0 only if the
* given iocb is for the SCSI device specified by vport, tgt_id and
* lun_id parameter.
* If ctx_cmd == LPFC_CTX_TGT, the function returns 0 only if the
* given iocb is for the SCSI target specified by vport and tgt_id
* parameters.
* If ctx_cmd == LPFC_CTX_HOST, the function returns 0 only if the
* given iocb is for the SCSI host associated with the given vport.
* This function is called with no locks held.
**/
static int static int
lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport, lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport,
uint16_t tgt_id, uint64_t lun_id, uint16_t tgt_id, uint64_t lun_id,
...@@ -3800,6 +4639,25 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport, ...@@ -3800,6 +4639,25 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport,
return rc; return rc;
} }
/**
* lpfc_sli_sum_iocb: Function to count the number of FCP iocbs pending.
* @vport: Pointer to virtual port.
* @tgt_id: SCSI ID of the target.
* @lun_id: LUN ID of the scsi device.
* @ctx_cmd: LPFC_CTX_LUN/LPFC_CTX_TGT/LPFC_CTX_HOST.
*
* This function returns number of FCP commands pending for the vport.
* When ctx_cmd == LPFC_CTX_LUN, the function returns number of FCP
* commands pending on the vport associated with SCSI device specified
* by tgt_id and lun_id parameters.
* When ctx_cmd == LPFC_CTX_TGT, the function returns number of FCP
* commands pending on the vport associated with SCSI target specified
* by tgt_id parameter.
* When ctx_cmd == LPFC_CTX_HOST, the function returns number of FCP
* commands pending on the vport.
* This function returns the number of iocbs which satisfy the filter.
* This function is called without any lock held.
**/
int int
lpfc_sli_sum_iocb(struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id, lpfc_sli_sum_iocb(struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id,
lpfc_ctx_cmd ctx_cmd) lpfc_ctx_cmd ctx_cmd)
...@@ -3819,6 +4677,17 @@ lpfc_sli_sum_iocb(struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id, ...@@ -3819,6 +4677,17 @@ lpfc_sli_sum_iocb(struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id,
return sum; return sum;
} }
/**
* lpfc_sli_abort_fcp_cmpl: Completion handler function for an aborted
* FCP iocb.
* @phba: Pointer to HBA context object
* @cmdiocb: Pointer to command iocb object.
* @rspiocb: Pointer to response iocb object.
*
* This function is called when an aborted FCP iocb completes. This
* function is called by the ring event handler with no lock held.
* This function frees the iocb.
**/
void void
lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb) struct lpfc_iocbq *rspiocb)
...@@ -3827,6 +4696,28 @@ lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -3827,6 +4696,28 @@ lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
return; return;
} }
/**
* lpfc_sli_abort_iocb: This function issue abort for all SCSI commands
* pending on a SCSI host(vport)/target/lun.
* @vport: Pointer to virtual port.
* @pring: Pointer to driver SLI ring object.
* @tgt_id: SCSI ID of the target.
* @lun_id: LUN ID of the scsi device.
* @abort_cmd: LPFC_CTX_LUN/LPFC_CTX_TGT/LPFC_CTX_HOST.
*
* This function sends an abort command for every SCSI command
* associated with the given virtual port pending on the ring
* filtered by lpfc_sli_validate_fcp_iocb function.
* When abort_cmd == LPFC_CTX_LUN, the function sends abort only to the
* FCP iocbs associated with lun specified by tgt_id and lun_id
* parameters
* When abort_cmd == LPFC_CTX_TGT, the function sends abort only to the
* FCP iocbs associated with SCSI target specified by tgt_id parameter.
* When abort_cmd == LPFC_CTX_HOST, the function sends abort to all
* FCP iocbs associated with virtual port.
* This function returns number of iocbs it failed to abort.
* This function is called with no locks held.
**/
int int
lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,
uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd abort_cmd) uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd abort_cmd)
...@@ -3878,6 +4769,24 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, ...@@ -3878,6 +4769,24 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,
return errcnt; return errcnt;
} }
/**
* lpfc_sli_wake_iocb_wait: iocb completion handler for iocb issued using
* lpfc_sli_issue_iocb_wait.
* @phba: Pointer to HBA context object.
* @cmdiocbq: Pointer to command iocb.
* @rspiocbq: Pointer to response iocb.
*
* This function is the completion handler for iocbs issued using
* lpfc_sli_issue_iocb_wait function. This function is called by the
* ring event handler function without any lock held. This function
* can be called from both worker thread context and interrupt
* context. This function also can be called from other thread which
* cleans up the SLI layer objects.
* This function copy the contents of the response iocb to the
* response iocb memory object provided by the caller of
* lpfc_sli_issue_iocb_wait and then wakes up the thread which
* sleeps for the iocb completion.
**/
static void static void
lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba, lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba,
struct lpfc_iocbq *cmdiocbq, struct lpfc_iocbq *cmdiocbq,
...@@ -3899,13 +4808,36 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba, ...@@ -3899,13 +4808,36 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba,
return; return;
} }
/* /**
* Issue the caller's iocb and wait for its completion, but no longer than the * lpfc_sli_issue_iocb_wait: Synchronous function to issue iocb commands.
* caller's timeout. Note that iocb_flags is cleared before the * @phba: Pointer to HBA context object..
* lpfc_sli_issue_call since the wake routine sets a unique value and by * @pring: Pointer to sli ring.
* definition this is a wait function. * @piocb: Pointer to command iocb.
*/ * @prspiocbq: Pointer to response iocb.
* @timeout: Timeout in number of seconds.
*
* This function issues the iocb to firmware and waits for the
* iocb to complete. If the iocb command is not
* completed within timeout seconds, it returns IOCB_TIMEDOUT.
* Caller should not free the iocb resources if this function
* returns IOCB_TIMEDOUT.
* The function waits for the iocb completion using an
* non-interruptible wait.
* This function will sleep while waiting for iocb completion.
* So, this function should not be called from any context which
* does not allow sleeping. Due to the same reason, this function
* cannot be called with interrupt disabled.
* This function assumes that the iocb completions occur while
* this function sleep. So, this function cannot be called from
* the thread which process iocb completion for this ring.
* This function clears the iocb_flag of the iocb object before
* issuing the iocb and the iocb completion handler sets this
* flag and wakes this thread when the iocb completes.
* The contents of the response iocb will be copied to prspiocbq
* by the completion handler when the command completes.
* This function returns IOCB_SUCCESS when success.
* This function is called with no lock held.
**/
int int
lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
struct lpfc_sli_ring *pring, struct lpfc_sli_ring *pring,
...@@ -3983,6 +4915,32 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, ...@@ -3983,6 +4915,32 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
return retval; return retval;
} }
/**
* lpfc_sli_issue_mbox_wait: Synchronous function to issue mailbox.
* @phba: Pointer to HBA context object.
* @pmboxq: Pointer to driver mailbox object.
* @timeout: Timeout in number of seconds.
*
* This function issues the mailbox to firmware and waits for the
* mailbox command to complete. If the mailbox command is not
* completed within timeout seconds, it returns MBX_TIMEOUT.
* The function waits for the mailbox completion using an
* interruptible wait. If the thread is woken up due to a
* signal, MBX_TIMEOUT error is returned to the caller. Caller
* should not free the mailbox resources, if this function returns
* MBX_TIMEOUT.
* This function will sleep while waiting for mailbox completion.
* So, this function should not be called from any context which
* does not allow sleeping. Due to the same reason, this function
* cannot be called with interrupt disabled.
* This function assumes that the mailbox completion occurs while
* this function sleep. So, this function cannot be called from
* the worker thread which processes mailbox completion.
* This function is called in the context of HBA management
* applications.
* This function returns MBX_SUCCESS when successful.
* This function is called with no lock held.
**/
int int
lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq, lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq,
uint32_t timeout) uint32_t timeout)
...@@ -4027,6 +4985,18 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq, ...@@ -4027,6 +4985,18 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq,
return retval; return retval;
} }
/**
* lpfc_sli_flush_mbox_queue: mailbox queue cleanup function.
* @phba: Pointer to HBA context.
*
* This function is called to cleanup any pending mailbox
* objects in the driver queue before bringing the HBA offline.
* This function is called while resetting the HBA.
* The function is called without any lock held. The function
* takes hbalock to update SLI data structure.
* This function returns 1 when there is an active mailbox
* command pending else returns 0.
**/
int int
lpfc_sli_flush_mbox_queue(struct lpfc_hba * phba) lpfc_sli_flush_mbox_queue(struct lpfc_hba * phba)
{ {
...@@ -4058,6 +5028,27 @@ lpfc_sli_flush_mbox_queue(struct lpfc_hba * phba) ...@@ -4058,6 +5028,27 @@ lpfc_sli_flush_mbox_queue(struct lpfc_hba * phba)
return (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE) ? 1 : 0; return (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE) ? 1 : 0;
} }
/**
* lpfc_intr_handler: The interrupt handler of lpfc driver.
* @irq: Interrupt number.
* @dev_id: The device context pointer.
*
* This function is called from the PCI layer when there is
* an event in the HBA which requires driver attention. When
* the PCI slot is in error recovery or the HBA is undergoing
* initialization the interrupt handler will not process the
* interrupt.
* The error attention, link attention and els ring attention
* events are handled by the worker thread. The interrupt
* handler signals the worker thread and returns for these
* events.
* The SCSI ring event and mailbox events are handled in the
* interrupt context.
* This function is called without any lock held. It gets the
* hbalock to access and update SLI data structures.
* This function returns IRQ_HANDLED when interrupt is handled
* else it returns IRQ_NONE.
**/
irqreturn_t irqreturn_t
lpfc_intr_handler(int irq, void *dev_id) lpfc_intr_handler(int irq, void *dev_id)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment