From 3ff5588d3f8afad65ded52ac0e4191462fe034cb Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 7 Sep 2010 11:44:01 -0400 Subject: [SCSI] sd: improve logic and efficiecy of media-change detection This patch (as1415) improves the formerly incomprehensible logic in sd_media_changed() (the current code refers to "changed" as a state, whereas in fact it is a relation between two states). It also adds a big comment so that everyone can understand what is really going on. The patch also improves efficiency by not reporting a media change when no medium was ever present. If no medium was present the last time we checked and there's still no medium, it's not necessary to tell the caller that a change occurred. Doing so merely causes the caller to attempt to revalidate a non-existent disk, which is a waste of time. Signed-off-by: Alan Stern Signed-off-by: James Bottomley --- drivers/scsi/sd.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 956496182c80..26f9d54a9c92 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -583,7 +583,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) * quietly refuse to do anything to a changed disc until * the changed bit has been reset */ - /* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */ + /* printk("SCSI disk has been changed or is not present. Prohibiting further I/O.\n"); */ goto out; } @@ -1023,7 +1023,6 @@ static int sd_media_changed(struct gendisk *disk) */ if (!scsi_device_online(sdp)) { set_media_not_present(sdkp); - retval = 1; goto out; } @@ -1054,7 +1053,6 @@ static int sd_media_changed(struct gendisk *disk) /* 0x3a is medium not present */ sshdr->asc == 0x3a)) { set_media_not_present(sdkp); - retval = 1; goto out; } @@ -1065,12 +1063,27 @@ static int sd_media_changed(struct gendisk *disk) */ sdkp->media_present = 1; - retval = sdp->changed; - sdp->changed = 0; out: - if (retval != sdkp->previous_state) + /* + * Report a media change under the following conditions: + * + * Medium is present now and wasn't present before. + * Medium wasn't present before and is present now. + * Medium was present at all times, but it changed while + * we weren't looking (sdp->changed is set). + * + * If there was no medium before and there is no medium now then + * don't report a change, even if a medium was inserted and removed + * while we weren't looking. + */ + retval = (sdkp->media_present != sdkp->previous_state || + (sdkp->media_present && sdp->changed)); + if (retval) sdev_evt_send_simple(sdp, SDEV_EVT_MEDIA_CHANGE, GFP_KERNEL); - sdkp->previous_state = retval; + sdkp->previous_state = sdkp->media_present; + + /* sdp->changed indicates medium was changed or is not present */ + sdp->changed = !sdkp->media_present; kfree(sshdr); return retval; } -- cgit v1.2.3-59-g8ed1b From 00f0254ed9b19164d416dc2e3c2e81eda55a6faf Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 1 Oct 2010 13:55:52 -0700 Subject: [SCSI] libsas: fix definition of wideport, include local sas address To date libsas has only looked at the attached sas address when determining the formation of wide ports. The specification and some hardware expects that phys with different addresses will not form a wide port unless the local peer phys also match each other. Introduce a flag to select stricter behavior at sas_register_ha() time. The flag can be dropped once it is known that all libsas users expect the same behavior. Current drivers just initialize this field to zero and get the traditional behavior. Reported-by: Patrick Thomson Signed-off-by: Dan Williams Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_port.c | 18 +++++++++++++----- include/scsi/libsas.h | 2 ++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c index fe8b74c706d2..5257fdfe699a 100644 --- a/drivers/scsi/libsas/sas_port.c +++ b/drivers/scsi/libsas/sas_port.c @@ -28,6 +28,17 @@ #include #include "../scsi_sas_internal.h" +static bool phy_is_wideport_member(struct asd_sas_port *port, struct asd_sas_phy *phy) +{ + struct sas_ha_struct *sas_ha = phy->ha; + + if (memcmp(port->attached_sas_addr, phy->attached_sas_addr, + SAS_ADDR_SIZE) != 0 || (sas_ha->strict_wide_ports && + memcmp(port->sas_addr, phy->sas_addr, SAS_ADDR_SIZE) != 0)) + return false; + return true; +} + /** * sas_form_port -- add this phy to a port * @phy: the phy of interest @@ -45,8 +56,7 @@ static void sas_form_port(struct asd_sas_phy *phy) unsigned long flags; if (port) { - if (memcmp(port->attached_sas_addr, phy->attached_sas_addr, - SAS_ADDR_SIZE) != 0) + if (!phy_is_wideport_member(port, phy)) sas_deform_port(phy); else { SAS_DPRINTK("%s: phy%d belongs to port%d already(%d)!\n", @@ -62,9 +72,7 @@ static void sas_form_port(struct asd_sas_phy *phy) port = sas_ha->sas_port[i]; spin_lock(&port->phy_list_lock); if (*(u64 *) port->sas_addr && - memcmp(port->attached_sas_addr, - phy->attached_sas_addr, SAS_ADDR_SIZE) == 0 && - port->num_phys > 0) { + phy_is_wideport_member(port, phy) && port->num_phys > 0) { /* wide port */ SAS_DPRINTK("phy%d matched wide port%d\n", phy->id, port->id); diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 90ce527ecf3d..8f6bb9c7f3eb 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -361,6 +361,8 @@ struct sas_ha_struct { /* The class calls this to send a task for execution. */ int lldd_max_execute_num; int lldd_queue_size; + int strict_wide_ports; /* both sas_addr and attached_sas_addr must match + * their siblings when forming wide ports */ /* LLDD calls these to notify the class of an event. */ void (*notify_ha_event)(struct sas_ha_struct *, enum ha_event); -- cgit v1.2.3-59-g8ed1b From 24d720b726c1a85f1962831ac30ad4d2ef8276b1 Mon Sep 17 00:00:00 2001 From: Luben Tuikov Date: Fri, 22 Oct 2010 21:24:36 -0700 Subject: [SCSI] Retrieve the Caching mode page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some kernel transport drivers unconditionally disable retrieval of the Caching mode page. One such for example is the BBB/CBI transport over USB.  Such a restraint is too harsh as some devices do support the Caching mode page. Unconditionally enabling the retrieval of this mode page over those transports at their transport code level may result in some devices failing and becoming unusable. This patch implements a method of retrieving the Caching mode page without unconditionally enabling it in the transports which unconditionally disable it. The idea is to ask for all supported pages, page code 0x3F, and then search for the Caching mode page in the mode parameter data returned. The sd driver already asks for all the mode pages supported by the attached device by setting the page code to 0x3F in order to find out if the media is write protected by reading the WP bit in the Device Specific Parameter field. It then attempts to retrieve only the Caching mode page by setting the page code to 8 and actually attempting to retrieve it if and only if the transport allows it. The method implemented here is that if the transport doesn't allow retrieval of the Caching mode page and the device is not RBC, then we ask for all pages supported by setting the page code to 0x3F (similarly to how the WP bit is retrieved above), and then we search for the Caching mode page in the mode parameter data returned. With this patch, devices over SATA, report this (no change): Oct 22 18:45:58 localhost kernel: sd 0:0:0:0: [sda] 976773168 512-byte logical blocks: (500 GB/465 GiB) Oct 22 18:45:58 localhost kernel: sd 0:0:0:0: Attached scsi generic sg0 type 0 Oct 22 18:45:58 localhost kernel: sd 0:0:0:0: [sda] Write Protect is off Oct 22 18:45:58 localhost kernel: sd 0:0:0:0: [sda] Mode Sense: 00 3a 00 00 Oct 22 18:45:58 localhost kernel: sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA Smart devices report their Caching mode page. This is a change where we'd previously see the kernel making assumption about the device's cache being write-through: Oct 22 18:45:58 localhost kernel: sd 6:0:0:0: Attached scsi generic sg2 type 0 Oct 22 18:45:58 localhost kernel: sd 6:0:0:0: [sdb] 610472646 4096-byte logical blocks: (2.50 TB/2.27 TiB) Oct 22 18:45:58 localhost kernel: sd 6:0:0:0: [sdb] Write Protect is off Oct 22 18:45:58 localhost kernel: sd 6:0:0:0: [sdb] Mode Sense: 47 00 10 08 Oct 22 18:45:58 localhost kernel: sd 6:0:0:0: [sdb] Write cache: enabled, read cache: enabled, supports DPO and FUA And "dumb" devices over BBB, are correctly shown not to support reporting the Caching mode page: Oct 22 18:49:06 localhost kernel: sd 7:0:0:0: [sdc] 15663104 512-byte logical blocks: (8.01 GB/7.46 GiB) Oct 22 18:49:06 localhost kernel: sd 7:0:0:0: [sdc] Write Protect is off Oct 22 18:49:06 localhost kernel: sd 7:0:0:0: [sdc] Mode Sense: 23 00 00 00 Oct 22 18:49:06 localhost kernel: sd 7:0:0:0: [sdc] No Caching mode page present Oct 22 18:49:06 localhost kernel: sd 7:0:0:0: [sdc] Assuming drive cache: write through Signed-off-by: Luben Tuikov Signed-off-by: James Bottomley --- drivers/scsi/sd.c | 63 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 26f9d54a9c92..d8e2caf9f468 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1915,10 +1915,14 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) int old_rcd = sdkp->RCD; int old_dpofua = sdkp->DPOFUA; - if (sdp->skip_ms_page_8) - goto defaults; - - if (sdp->type == TYPE_RBC) { + if (sdp->skip_ms_page_8) { + if (sdp->type == TYPE_RBC) + goto defaults; + else { + modepage = 0x3F; + dbd = 0; + } + } else if (sdp->type == TYPE_RBC) { modepage = 6; dbd = 8; } else { @@ -1946,13 +1950,11 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) */ if (len < 3) goto bad_sense; - if (len > 20) - len = 20; - - /* Take headers and block descriptors into account */ - len += data.header_length + data.block_descriptor_length; - if (len > SD_BUF_SIZE) - goto bad_sense; + else if (len > SD_BUF_SIZE) { + sd_printk(KERN_NOTICE, sdkp, "Truncating mode parameter " + "data from %d to %d bytes\n", len, SD_BUF_SIZE); + len = SD_BUF_SIZE; + } /* Get the data */ res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr); @@ -1960,16 +1962,45 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) if (scsi_status_is_good(res)) { int offset = data.header_length + data.block_descriptor_length; - if (offset >= SD_BUF_SIZE - 2) { - sd_printk(KERN_ERR, sdkp, "Malformed MODE SENSE response\n"); - goto defaults; + while (offset < len) { + u8 page_code = buffer[offset] & 0x3F; + u8 spf = buffer[offset] & 0x40; + + if (page_code == 8 || page_code == 6) { + /* We're interested only in the first 3 bytes. + */ + if (len - offset <= 2) { + sd_printk(KERN_ERR, sdkp, "Incomplete " + "mode parameter data\n"); + goto defaults; + } else { + modepage = page_code; + goto Page_found; + } + } else { + /* Go to the next page */ + if (spf && len - offset > 3) + offset += 4 + (buffer[offset+2] << 8) + + buffer[offset+3]; + else if (!spf && len - offset > 1) + offset += 2 + buffer[offset+1]; + else { + sd_printk(KERN_ERR, sdkp, "Incomplete " + "mode parameter data\n"); + goto defaults; + } + } } - if ((buffer[offset] & 0x3f) != modepage) { + if (modepage == 0x3F) { + sd_printk(KERN_ERR, sdkp, "No Caching mode page " + "present\n"); + goto defaults; + } else if ((buffer[offset] & 0x3f) != modepage) { sd_printk(KERN_ERR, sdkp, "Got wrong page\n"); goto defaults; } - + Page_found: if (modepage == 8) { sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0); sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0); -- cgit v1.2.3-59-g8ed1b From 0cb992eda1f7e7672775032378690baa87c0e13d Mon Sep 17 00:00:00 2001 From: Wayne Boyer Date: Thu, 4 Nov 2010 09:35:58 -0700 Subject: [SCSI] ipr: fix lun assignment and comparison The lun value was not getting set up correctly for all devices attached to the new 64 bit adapters. The fix is to move the logic to earlier in the ipr_init_res_entry routine such that the value does get set correctly for all devices. Then the ipr_is_same_device comparison function was using the wrong lun value in the logic for the new adapters. Change this to use the correct lun value. Signed-off-by: Wayne Boyer Acked-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 5bbaee597e88..04c1cea89dbe 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -1048,6 +1048,8 @@ static void ipr_init_res_entry(struct ipr_resource_entry *res, sizeof(res->res_path)); res->bus = 0; + memcpy(&res->dev_lun.scsi_lun, &cfgtew->u.cfgte64->lun, + sizeof(res->dev_lun.scsi_lun)); res->lun = scsilun_to_int(&res->dev_lun); if (res->type == IPR_RES_TYPE_GENERIC_SCSI) { @@ -1063,9 +1065,6 @@ static void ipr_init_res_entry(struct ipr_resource_entry *res, ioa_cfg->max_devs_supported); set_bit(res->target, ioa_cfg->target_ids); } - - memcpy(&res->dev_lun.scsi_lun, &cfgtew->u.cfgte64->lun, - sizeof(res->dev_lun.scsi_lun)); } else if (res->type == IPR_RES_TYPE_IOAFP) { res->bus = IPR_IOAFP_VIRTUAL_BUS; res->target = 0; @@ -1116,7 +1115,7 @@ static int ipr_is_same_device(struct ipr_resource_entry *res, if (res->ioa_cfg->sis64) { if (!memcmp(&res->dev_id, &cfgtew->u.cfgte64->dev_id, sizeof(cfgtew->u.cfgte64->dev_id)) && - !memcmp(&res->lun, &cfgtew->u.cfgte64->lun, + !memcmp(&res->dev_lun.scsi_lun, &cfgtew->u.cfgte64->lun, sizeof(cfgtew->u.cfgte64->lun))) { return 1; } -- cgit v1.2.3-59-g8ed1b From 110def851fc823bb1a4584cb6308e30e5ffb3e05 Mon Sep 17 00:00:00 2001 From: Wayne Boyer Date: Thu, 4 Nov 2010 09:36:16 -0700 Subject: [SCSI] ipr: fix mailbox register definition and add a delay before reading The definition for the mailbox register for new adapters was incorrect. The value has been updated to the correct offset. After an adapter reset, the mailbox register on the new adapters takes a number of seconds to stabilize. A delay has been added before reading the register. Signed-off-by: Wayne Boyer Acked-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 47 +++++++++++++++++++++++++++++++++++++++++------ drivers/scsi/ipr.h | 2 ++ 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 04c1cea89dbe..de2e09e49a3e 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -146,7 +146,7 @@ static const struct ipr_chip_cfg_t ipr_chip_cfg[] = { } }, { /* CRoC */ - .mailbox = 0x00040, + .mailbox = 0x00044, .cache_line_size = 0x20, { .set_interrupt_mask_reg = 0x00010, @@ -2900,6 +2900,12 @@ static void ipr_get_ioa_dump(struct ipr_ioa_cfg *ioa_cfg, struct ipr_dump *dump) return; } + if (ioa_cfg->sis64) { + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + ssleep(IPR_DUMP_DELAY_SECONDS); + spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); + } + start_addr = readl(ioa_cfg->ioa_mailbox); if (!ioa_cfg->sis64 && !ipr_sdt_is_fmt2(start_addr)) { @@ -7471,6 +7477,29 @@ static void ipr_get_unit_check_buffer(struct ipr_ioa_cfg *ioa_cfg) list_add_tail(&hostrcb->queue, &ioa_cfg->hostrcb_free_q); } +/** + * ipr_reset_get_unit_check_job - Call to get the unit check buffer. + * @ipr_cmd: ipr command struct + * + * Description: This function will call to get the unit check buffer. + * + * Return value: + * IPR_RC_JOB_RETURN + **/ +static int ipr_reset_get_unit_check_job(struct ipr_cmnd *ipr_cmd) +{ + struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; + + ENTER; + ioa_cfg->ioa_unit_checked = 0; + ipr_get_unit_check_buffer(ioa_cfg); + ipr_cmd->job_step = ipr_reset_alert; + ipr_reset_start_timer(ipr_cmd, 0); + + LEAVE; + return IPR_RC_JOB_RETURN; +} + /** * ipr_reset_restore_cfg_space - Restore PCI config space. * @ipr_cmd: ipr command struct @@ -7511,11 +7540,17 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) } if (ioa_cfg->ioa_unit_checked) { - ioa_cfg->ioa_unit_checked = 0; - ipr_get_unit_check_buffer(ioa_cfg); - ipr_cmd->job_step = ipr_reset_alert; - ipr_reset_start_timer(ipr_cmd, 0); - return IPR_RC_JOB_RETURN; + if (ioa_cfg->sis64) { + ipr_cmd->job_step = ipr_reset_get_unit_check_job; + ipr_reset_start_timer(ipr_cmd, IPR_DUMP_DELAY_TIMEOUT); + return IPR_RC_JOB_RETURN; + } else { + ioa_cfg->ioa_unit_checked = 0; + ipr_get_unit_check_buffer(ioa_cfg); + ipr_cmd->job_step = ipr_reset_alert; + ipr_reset_start_timer(ipr_cmd, 0); + return IPR_RC_JOB_RETURN; + } } if (ioa_cfg->in_ioa_bringdown) { diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index b28a00f1082c..13f425fb8851 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -218,6 +218,8 @@ #define IPR_WAIT_FOR_BIST_TIMEOUT (2 * HZ) #define IPR_PCI_RESET_TIMEOUT (HZ / 2) #define IPR_DUMP_TIMEOUT (15 * HZ) +#define IPR_DUMP_DELAY_SECONDS 4 +#define IPR_DUMP_DELAY_TIMEOUT (IPR_DUMP_DELAY_SECONDS * HZ) /* * SCSI Literals -- cgit v1.2.3-59-g8ed1b From 98db519573e805f9f7e988fb5661da951fcb16b1 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Mon, 25 Oct 2010 15:53:41 -0500 Subject: [SCSI] fix id computation in scsi_eh_target_reset() The current code in scsi_eh_target_reset() has an off by one error that actually sends spurious extra resets. Since there's no real need to reset the targets in numerical order, simply chunk up the command recovery list doing target resets and pulling matching targets out of the list (that also makes the loop O(N) instead of O(N^2). [mike christie found and fixed a list_splice -> list_splice_init problem] Reported-by: Hillf Danton Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 61 +++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 36 deletions(-) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 30ac116186f5..45c75649b9e0 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1124,51 +1124,40 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost, struct list_head *work_q, struct list_head *done_q) { - struct scsi_cmnd *scmd, *tgtr_scmd, *next; - unsigned int id = 0; - int rtn; + LIST_HEAD(tmp_list); - do { - tgtr_scmd = NULL; - list_for_each_entry(scmd, work_q, eh_entry) { - if (id == scmd_id(scmd)) { - tgtr_scmd = scmd; - break; - } - } - if (!tgtr_scmd) { - /* not one exactly equal; find the next highest */ - list_for_each_entry(scmd, work_q, eh_entry) { - if (scmd_id(scmd) > id && - (!tgtr_scmd || - scmd_id(tgtr_scmd) > scmd_id(scmd))) - tgtr_scmd = scmd; - } - } - if (!tgtr_scmd) - /* no more commands, that's it */ - break; + list_splice_init(work_q, &tmp_list); + + while (!list_empty(&tmp_list)) { + struct scsi_cmnd *next, *scmd; + int rtn; + unsigned int id; + + scmd = list_entry(tmp_list.next, struct scsi_cmnd, eh_entry); + id = scmd_id(scmd); SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending target reset " "to target %d\n", current->comm, id)); - rtn = scsi_try_target_reset(tgtr_scmd); - if (rtn == SUCCESS || rtn == FAST_IO_FAIL) { - list_for_each_entry_safe(scmd, next, work_q, eh_entry) { - if (id == scmd_id(scmd)) - if (!scsi_device_online(scmd->device) || - rtn == FAST_IO_FAIL || - !scsi_eh_tur(tgtr_scmd)) - scsi_eh_finish_cmd(scmd, - done_q); - } - } else + rtn = scsi_try_target_reset(scmd); + if (rtn != SUCCESS && rtn != FAST_IO_FAIL) SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Target reset" " failed target: " "%d\n", current->comm, id)); - id++; - } while(id != 0); + list_for_each_entry_safe(scmd, next, &tmp_list, eh_entry) { + if (scmd_id(scmd) != id) + continue; + + if ((rtn == SUCCESS || rtn == FAST_IO_FAIL) + && (!scsi_device_online(scmd->device) || + rtn == FAST_IO_FAIL || !scsi_eh_tur(scmd))) + scsi_eh_finish_cmd(scmd, done_q); + else + /* push back on work queue for further processing */ + list_move(&scmd->eh_entry, work_q); + } + } return list_empty(work_q); } -- cgit v1.2.3-59-g8ed1b From 63e801ce685d151c5faca8f491adc2ad2e732259 Mon Sep 17 00:00:00 2001 From: James Smart Date: Sat, 20 Nov 2010 23:14:19 -0500 Subject: [SCSI] lpfc 8.3.19: Fix critical errors and crashes Fix critical errors and crashes - Replace LOF_SECURITY with LOG_SECURITY - When calculating diag test memory size, use full size with header. - Return LS_RJT with status=UNSUPPORTED on unrecognized ELS's - Correct NULL pointer dereference when lpfc_create_vport_work_array() returns NULL. - Added code to handle CVL when port is in LPFC_VPORT_FAILED state. - In lpfc_do_scr_ns_plogi, check the nodelist for FDMI_DID and reuse the resource. - Check for generic request 64 and calculate the sgl offset for the request and reply sgls, also calculate the xmit length using only the request bde. Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_bsg.c | 4 +-- drivers/scsi/lpfc/lpfc_els.c | 31 ++++++++++++++------ drivers/scsi/lpfc/lpfc_hbadisc.c | 9 ++++++ drivers/scsi/lpfc/lpfc_init.c | 6 ++-- drivers/scsi/lpfc/lpfc_logmsg.h | 2 +- drivers/scsi/lpfc/lpfc_sli.c | 61 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 99 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 7260c3af555a..c216f4eb0e37 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -2162,7 +2162,7 @@ lpfc_bsg_diag_test(struct fc_bsg_job *job) goto loopback_test_exit; } - if (size >= BUF_SZ_4K) { + if (full_size >= BUF_SZ_4K) { /* * Allocate memory for ioctl data. If buffer is bigger than 64k, * then we allocate 64k and re-use that buffer over and over to @@ -2171,7 +2171,7 @@ lpfc_bsg_diag_test(struct fc_bsg_job *job) * problem with GET_FCPTARGETMAPPING... */ if (size <= (64 * 1024)) - total_mem = size; + total_mem = full_size; else total_mem = 64 * 1024; } else diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 884f4d321799..196a7bf905a1 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -6201,7 +6201,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, cmd, did, vport->port_state); /* Unsupported ELS command, reject */ - rjt_err = LSRJT_INVALID_CMD; + rjt_err = LSRJT_CMD_UNSUPPORTED; /* Unknown ELS command received from NPORT */ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, @@ -6408,18 +6408,31 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport) } if (vport->cfg_fdmi_on) { - ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool, - GFP_KERNEL); + /* If this is the first time, allocate an ndlp and initialize + * it. Otherwise, make sure the node is enabled and then do the + * login. + */ + ndlp_fdmi = lpfc_findnode_did(vport, FDMI_DID); + if (!ndlp_fdmi) { + ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool, + GFP_KERNEL); + if (ndlp_fdmi) { + lpfc_nlp_init(vport, ndlp_fdmi, FDMI_DID); + ndlp_fdmi->nlp_type |= NLP_FABRIC; + } else + return; + } + if (!NLP_CHK_NODE_ACT(ndlp_fdmi)) + ndlp_fdmi = lpfc_enable_node(vport, + ndlp_fdmi, + NLP_STE_NPR_NODE); + if (ndlp_fdmi) { - lpfc_nlp_init(vport, ndlp_fdmi, FDMI_DID); - ndlp_fdmi->nlp_type |= NLP_FABRIC; lpfc_nlp_set_state(vport, ndlp_fdmi, - NLP_STE_PLOGI_ISSUE); - lpfc_issue_els_plogi(vport, ndlp_fdmi->nlp_DID, - 0); + NLP_STE_PLOGI_ISSUE); + lpfc_issue_els_plogi(vport, ndlp_fdmi->nlp_DID, 0); } } - return; } /** diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index a5d1695dac3d..57ab799da2e2 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -4059,6 +4059,11 @@ lpfc_unreg_hba_rpis(struct lpfc_hba *phba) int i; vports = lpfc_create_vport_work_array(phba); + if (!vports) { + lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, + "2884 Vport array allocation failed \n"); + return; + } for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { shost = lpfc_shost_from_vport(vports[i]); spin_lock_irq(shost->host_lock); @@ -5254,6 +5259,10 @@ lpfc_fcf_inuse(struct lpfc_hba *phba) vports = lpfc_create_vport_work_array(phba); + /* If driver cannot allocate memory, indicate fcf is in use */ + if (!vports) + return 1; + for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { shost = lpfc_shost_from_vport(vports[i]); spin_lock_irq(shost->host_lock); diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index b3065791f303..ec8e8e819236 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -3247,10 +3247,12 @@ lpfc_sli4_perform_vport_cvl(struct lpfc_vport *vport) if (!ndlp) return 0; } - if (phba->pport->port_state < LPFC_FLOGI) + if ((phba->pport->port_state < LPFC_FLOGI) && + (phba->pport->port_state != LPFC_VPORT_FAILED)) return NULL; /* If virtual link is not yet instantiated ignore CVL */ - if ((vport != phba->pport) && (vport->port_state < LPFC_FDISC)) + if ((vport != phba->pport) && (vport->port_state < LPFC_FDISC) + && (vport->port_state != LPFC_VPORT_FAILED)) return NULL; shost = lpfc_shost_from_vport(vport); if (!shost) diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h index bb59e9273126..e3b790e59156 100644 --- a/drivers/scsi/lpfc/lpfc_logmsg.h +++ b/drivers/scsi/lpfc/lpfc_logmsg.h @@ -33,7 +33,7 @@ #define LOG_FCP_ERROR 0x00001000 /* log errors, not underruns */ #define LOG_LIBDFC 0x00002000 /* Libdfc events */ #define LOG_VPORT 0x00004000 /* NPIV events */ -#define LOF_SECURITY 0x00008000 /* Security events */ +#define LOG_SECURITY 0x00008000 /* Security events */ #define LOG_EVENT 0x00010000 /* CT,TEMP,DUMP, logging */ #define LOG_FIP 0x00020000 /* FIP events */ #define LOG_ALL_MSG 0xffffffff /* LOG all messages */ diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 554efa6623f4..06b1655b4d59 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -5863,6 +5863,8 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, IOCB_t *icmd; int numBdes = 0; int i = 0; + uint32_t offset = 0; /* accumulated offset in the sg request list */ + int inbound = 0; /* number of sg reply entries inbound from firmware */ if (!piocbq || !sglq) return xritag; @@ -5897,6 +5899,20 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, */ bde.tus.w = le32_to_cpu(bpl->tus.w); sgl->sge_len = cpu_to_le32(bde.tus.f.bdeSize); + /* The offsets in the sgl need to be accumulated + * separately for the request and reply lists. + * The request is always first, the reply follows. + */ + if (piocbq->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) { + /* add up the reply sg entries */ + if (bpl->tus.f.bdeFlags == BUFF_TYPE_BDE_64I) + inbound++; + /* first inbound? reset the offset */ + if (inbound == 1) + offset = 0; + bf_set(lpfc_sli4_sge_offset, sgl, offset); + offset += bde.tus.f.bdeSize; + } bpl++; sgl++; } @@ -6140,6 +6156,18 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, bf_set(wqe_ebde_cnt, &wqe->fcp_icmd.wqe_com, 0); break; case CMD_GEN_REQUEST64_CR: + /* For this command calculate the xmit length of the + * request bde. + */ + xmit_len = 0; + numBdes = iocbq->iocb.un.genreq64.bdl.bdeSize / + sizeof(struct ulp_bde64); + for (i = 0; i < numBdes; i++) { + if (bpl[i].tus.f.bdeFlags != BUFF_TYPE_BDE_64) + break; + bde.tus.w = le32_to_cpu(bpl[i].tus.w); + xmit_len += bde.tus.f.bdeSize; + } /* word3 iocb=IO_TAG wqe=request_payload_len */ wqe->gen_req.request_payload_len = xmit_len; /* word4 iocb=parameter wqe=relative_offset memcpy */ @@ -12854,6 +12882,7 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport) struct lpfc_nodelist *act_mbx_ndlp = NULL; struct Scsi_Host *shost = lpfc_shost_from_vport(vport); LIST_HEAD(mbox_cmd_list); + uint8_t restart_loop; /* Clean up internally queued mailbox commands with the vport */ spin_lock_irq(&phba->hbalock); @@ -12882,6 +12911,38 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport) mb->mbox_flag |= LPFC_MBX_IMED_UNREG; } } + /* Cleanup any mailbox completions which are not yet processed */ + do { + restart_loop = 0; + list_for_each_entry(mb, &phba->sli.mboxq_cmpl, list) { + /* + * If this mailox is already processed or it is + * for another vport ignore it. + */ + if ((mb->vport != vport) || + (mb->mbox_flag & LPFC_MBX_IMED_UNREG)) + continue; + + if ((mb->u.mb.mbxCommand != MBX_REG_LOGIN64) && + (mb->u.mb.mbxCommand != MBX_REG_VPI)) + continue; + + mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; + if (mb->u.mb.mbxCommand == MBX_REG_LOGIN64) { + ndlp = (struct lpfc_nodelist *)mb->context2; + /* Unregister the RPI when mailbox complete */ + mb->mbox_flag |= LPFC_MBX_IMED_UNREG; + restart_loop = 1; + spin_unlock_irq(&phba->hbalock); + spin_lock(shost->host_lock); + ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL; + spin_unlock(shost->host_lock); + spin_lock_irq(&phba->hbalock); + break; + } + } + } while (restart_loop); + spin_unlock_irq(&phba->hbalock); /* Release the cleaned-up mailbox commands */ -- cgit v1.2.3-59-g8ed1b From 085c647c3377c3e39c8c572278507b1e1c7e7bf7 Mon Sep 17 00:00:00 2001 From: James Smart Date: Sat, 20 Nov 2010 23:11:37 -0500 Subject: [SCSI] lpfc 8.3.19: Add latest SLI4 Hardware initialization support - Add the Lancer FC and FCoE PCI IDs - Add new SLI4 INTF register definitions - Implement new SLI4 doorbell register Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_hw.h | 6 +- drivers/scsi/lpfc/lpfc_hw4.h | 128 +++++++++++++++++++++++++++++++++++------- drivers/scsi/lpfc/lpfc_init.c | 48 ++++++++++++---- 3 files changed, 149 insertions(+), 33 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 9b8333456465..1044c438bb95 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -1172,7 +1172,10 @@ typedef struct { #define PCI_VENDOR_ID_EMULEX 0x10df #define PCI_DEVICE_ID_FIREFLY 0x1ae5 #define PCI_DEVICE_ID_PROTEUS_VF 0xe100 +#define PCI_DEVICE_ID_BALIUS 0xe131 #define PCI_DEVICE_ID_PROTEUS_PF 0xe180 +#define PCI_DEVICE_ID_LANCER_FC 0xe200 +#define PCI_DEVICE_ID_LANCER_FCOE 0xe260 #define PCI_DEVICE_ID_SAT_SMB 0xf011 #define PCI_DEVICE_ID_SAT_MID 0xf015 #define PCI_DEVICE_ID_RFLY 0xf095 @@ -1189,6 +1192,7 @@ typedef struct { #define PCI_DEVICE_ID_SAT 0xf100 #define PCI_DEVICE_ID_SAT_SCSP 0xf111 #define PCI_DEVICE_ID_SAT_DCSP 0xf112 +#define PCI_DEVICE_ID_FALCON 0xf180 #define PCI_DEVICE_ID_SUPERFLY 0xf700 #define PCI_DEVICE_ID_DRAGONFLY 0xf800 #define PCI_DEVICE_ID_CENTAUR 0xf900 @@ -1210,8 +1214,6 @@ typedef struct { #define PCI_VENDOR_ID_SERVERENGINE 0x19a2 #define PCI_DEVICE_ID_TIGERSHARK 0x0704 #define PCI_DEVICE_ID_TOMCAT 0x0714 -#define PCI_DEVICE_ID_FALCON 0xf180 -#define PCI_DEVICE_ID_BALIUS 0xe131 #define JEDEC_ID_ADDRESS 0x0080001c #define FIREFLY_JEDEC_ID 0x1ACC diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 6e4bc34e1d0d..7fbc58713f19 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -64,29 +64,39 @@ struct lpfc_sli_intf { #define lpfc_sli_intf_valid_MASK 0x00000007 #define lpfc_sli_intf_valid_WORD word0 #define LPFC_SLI_INTF_VALID 6 -#define lpfc_sli_intf_featurelevel2_SHIFT 24 -#define lpfc_sli_intf_featurelevel2_MASK 0x0000001F -#define lpfc_sli_intf_featurelevel2_WORD word0 -#define lpfc_sli_intf_featurelevel1_SHIFT 16 -#define lpfc_sli_intf_featurelevel1_MASK 0x000000FF -#define lpfc_sli_intf_featurelevel1_WORD word0 -#define LPFC_SLI_INTF_FEATURELEVEL1_1 1 -#define LPFC_SLI_INTF_FEATURELEVEL1_2 2 +#define lpfc_sli_intf_sli_hint2_SHIFT 24 +#define lpfc_sli_intf_sli_hint2_MASK 0x0000001F +#define lpfc_sli_intf_sli_hint2_WORD word0 +#define LPFC_SLI_INTF_SLI_HINT2_NONE 0 +#define lpfc_sli_intf_sli_hint1_SHIFT 16 +#define lpfc_sli_intf_sli_hint1_MASK 0x000000FF +#define lpfc_sli_intf_sli_hint1_WORD word0 +#define LPFC_SLI_INTF_SLI_HINT1_NONE 0 +#define LPFC_SLI_INTF_SLI_HINT1_1 1 +#define LPFC_SLI_INTF_SLI_HINT1_2 2 +#define lpfc_sli_intf_if_type_SHIFT 12 +#define lpfc_sli_intf_if_type_MASK 0x0000000F +#define lpfc_sli_intf_if_type_WORD word0 +#define LPFC_SLI_INTF_IF_TYPE_0 0 +#define LPFC_SLI_INTF_IF_TYPE_1 1 +#define LPFC_SLI_INTF_IF_TYPE_2 2 #define lpfc_sli_intf_sli_family_SHIFT 8 -#define lpfc_sli_intf_sli_family_MASK 0x000000FF +#define lpfc_sli_intf_sli_family_MASK 0x0000000F #define lpfc_sli_intf_sli_family_WORD word0 -#define LPFC_SLI_INTF_FAMILY_BE2 0 -#define LPFC_SLI_INTF_FAMILY_BE3 1 +#define LPFC_SLI_INTF_FAMILY_BE2 0x0 +#define LPFC_SLI_INTF_FAMILY_BE3 0x1 +#define LPFC_SLI_INTF_FAMILY_LNCR_A0 0xa +#define LPFC_SLI_INTF_FAMILY_LNCR_B0 0xb #define lpfc_sli_intf_slirev_SHIFT 4 #define lpfc_sli_intf_slirev_MASK 0x0000000F #define lpfc_sli_intf_slirev_WORD word0 #define LPFC_SLI_INTF_REV_SLI3 3 #define LPFC_SLI_INTF_REV_SLI4 4 -#define lpfc_sli_intf_if_type_SHIFT 0 -#define lpfc_sli_intf_if_type_MASK 0x00000007 -#define lpfc_sli_intf_if_type_WORD word0 -#define LPFC_SLI_INTF_IF_TYPE_0 0 -#define LPFC_SLI_INTF_IF_TYPE_1 1 +#define lpfc_sli_intf_func_type_SHIFT 0 +#define lpfc_sli_intf_func_type_MASK 0x00000001 +#define lpfc_sli_intf_func_type_WORD word0 +#define LPFC_SLI_INTF_IF_TYPE_PHYS 0 +#define LPFC_SLI_INTF_IF_TYPE_VIRT 1 }; #define LPFC_SLI4_MBX_EMBED true @@ -450,13 +460,15 @@ struct lpfc_register { uint32_t word0; }; +/* The SLI4 INTF register offset is common to all if_type values. */ +#define LPFC_SLI_INTF 0x0058 + +/* The following BAR0 Registers apply to SLI4 if_type 0 UCNAs. */ #define LPFC_UERR_STATUS_HI 0x00A4 #define LPFC_UERR_STATUS_LO 0x00A0 #define LPFC_UE_MASK_HI 0x00AC #define LPFC_UE_MASK_LO 0x00A8 -#define LPFC_SLI_INTF 0x0058 -/* BAR0 Registers */ #define LPFC_HST_STATE 0x00AC #define lpfc_hst_state_perr_SHIFT 31 #define lpfc_hst_state_perr_MASK 0x1 @@ -480,6 +492,10 @@ struct lpfc_register { #define lpfc_hst_state_port_status_MASK 0xFFFF #define lpfc_hst_state_port_status_WORD word0 +/* + * The following Port Status Values apply to SLI4, if_type 0 and 2 + * UCNAs. + */ #define LPFC_POST_STAGE_POWER_ON_RESET 0x0000 #define LPFC_POST_STAGE_AWAITING_HOST_RDY 0x0001 #define LPFC_POST_STAGE_HOST_RDY 0x0002 @@ -514,6 +530,64 @@ struct lpfc_register { #define LPFC_POST_STAGE_ARMFW_READY 0xC000 #define LPFC_POST_STAGE_ARMFW_UE 0xF000 + +/* The following BAR0 register sets are defined for if_type 2 UCNAs. */ +#define LPFC_SLIPORT_SEMAPHORE 0x0400 +#define lpfc_sliport_smphr_perr_SHIFT 31 +#define lpfc_sliport_smphr_perr_MASK 0x1 +#define lpfc_sliport_smphr_perr_WORD word0 +#define lpfc_sliport_smphr_sfi_SHIFT 30 +#define lpfc_sliport_smphr_sfi_MASK 0x1 +#define lpfc_sliport_smphr_sfi_WORD word0 +#define lpfc_sliport_smphr_nip_SHIFT 29 +#define lpfc_sliport_smphr_nip_MASK 0x1 +#define lpfc_sliport_smphr_nip_WORD word0 +#define lpfc_sliport_smphr_ipc_SHIFT 28 +#define lpfc_sliport_smphr_ipc_MASK 0x1 +#define lpfc_sliport_smphr_ipc_WORD word0 +#define lpfc_sliport_smphr_scr1_SHIFT 27 +#define lpfc_sliport_smphr_scr1_MASK 0x1 +#define lpfc_sliport_smphr_scr1_WORD word0 +#define lpfc_sliport_smphr_scr2_SHIFT 26 +#define lpfc_sliport_smphr_scr2_MASK 0x1 +#define lpfc_sliport_smphr_scr2_WORD word0 +#define lpfc_sliport_smphr_host_scratch_SHIFT 16 +#define lpfc_sliport_smphr_host_scratch_MASK 0xFF +#define lpfc_sliport_smphr_host_scratch_WORD word0 +#define lpfc_sliport_smphr_port_status_SHIFT 0 +#define lpfc_sliport_smphr_port_status_MASK 0xFFFF +#define lpfc_sliport_smphr_port_status_WORD word0 + +#define LPFC_SLIPORT_STATUS 0x0404 +#define lpfc_sliport_status_err_SHIFT 31 +#define lpfc_sliport_status_err_MASK 0x1 +#define lpfc_sliport_status_err_WORD word0 +#define lpfc_sliport_status_end_SHIFT 30 +#define lpfc_sliport_status_end_MASK 0x1 +#define lpfc_sliport_status_end_WORD word0 +#define lpfc_sliport_status_oti_SHIFT 29 +#define lpfc_sliport_status_oti_MASK 0x1 +#define lpfc_sliport_status_oti_WORD word0 +#define lpfc_sliport_status_rn_SHIFT 24 +#define lpfc_sliport_status_rn_MASK 0x1 +#define lpfc_sliport_status_rn_WORD word0 +#define lpfc_sliport_status_rdy_SHIFT 23 +#define lpfc_sliport_status_rdy_MASK 0x1 +#define lpfc_sliport_status_rdy_WORD word0 + +#define LPFC_SLIPORT_CONTROL 0x0408 +#define lpfc_sliport_ctrl_end_SHIFT 30 +#define lpfc_sliport_ctrl_end_MASK 0x1 +#define lpfc_sliport_ctrl_end_WORD word0 +#define LPFC_SLIPORT_LITTLE_ENDIAN 0 +#define LPFC_SLIPORT_BIG_ENDIAN 1 +#define lpfc_sliport_ctrl_ip_SHIFT 27 +#define lpfc_sliport_ctrl_ip_MASK 0x1 +#define lpfc_sliport_ctrl_ip_WORD word0 + +#define LPFC_SLIPORT_ERROR_1 0x040C +#define LPFC_SLIPORT_ERROR_2 0x0410 + /* BAR1 Registers */ #define LPFC_IMR_MASK_ALL 0xFFFFFFFF #define LPFC_ISCR_CLEAR_ALL 0xFFFFFFFF @@ -569,14 +643,21 @@ struct lpfc_register { #define LPFC_SLI4_INTR30 BIT30 #define LPFC_SLI4_INTR31 BIT31 -/* BAR2 Registers */ +/* + * The Doorbell registers defined here exist in different BAR + * register sets depending on the UCNA Port's reported if_type + * value. For UCNA ports running SLI4 and if_type 0, they reside in + * BAR2. For UCNA ports running SLI4 and if_type 2, they reside in + * BAR0. The offsets are the same so the driver must account for + * any base address difference. + */ #define LPFC_RQ_DOORBELL 0x00A0 #define lpfc_rq_doorbell_num_posted_SHIFT 16 #define lpfc_rq_doorbell_num_posted_MASK 0x3FFF #define lpfc_rq_doorbell_num_posted_WORD word0 #define LPFC_RQ_POST_BATCH 8 /* RQEs to post at one time */ #define lpfc_rq_doorbell_id_SHIFT 0 -#define lpfc_rq_doorbell_id_MASK 0x03FF +#define lpfc_rq_doorbell_id_MASK 0xFFFF #define lpfc_rq_doorbell_id_WORD word0 #define LPFC_WQ_DOORBELL 0x0040 @@ -591,6 +672,11 @@ struct lpfc_register { #define lpfc_wq_doorbell_id_WORD word0 #define LPFC_EQCQ_DOORBELL 0x0120 +#define lpfc_eqcq_doorbell_se_SHIFT 31 +#define lpfc_eqcq_doorbell_se_MASK 0x0001 +#define lpfc_eqcq_doorbell_se_WORD word0 +#define LPFC_EQCQ_SOLICIT_ENABLE_OFF 0 +#define LPFC_EQCQ_SOLICIT_ENABLE_ON 1 #define lpfc_eqcq_doorbell_arm_SHIFT 29 #define lpfc_eqcq_doorbell_arm_MASK 0x0001 #define lpfc_eqcq_doorbell_arm_WORD word0 @@ -628,7 +714,7 @@ struct lpfc_register { #define lpfc_mq_doorbell_num_posted_MASK 0x3FFF #define lpfc_mq_doorbell_num_posted_WORD word0 #define lpfc_mq_doorbell_id_SHIFT 0 -#define lpfc_mq_doorbell_id_MASK 0x03FF +#define lpfc_mq_doorbell_id_MASK 0xFFFF #define lpfc_mq_doorbell_id_WORD word0 struct lpfc_sli4_cfg_mhdr { diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index ec8e8e819236..912b5959f068 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -1853,6 +1853,14 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp) m = (typeof(m)){"LPVe12002", "PCIe Shared I/O", "Fibre Channel Adapter"}; break; + case PCI_DEVICE_ID_LANCER_FC: + oneConnect = 1; + m = (typeof(m)){"Undefined", "PCIe", "Fibre Channel Adapter"}; + break; + case PCI_DEVICE_ID_LANCER_FCOE: + oneConnect = 1; + m = (typeof(m)){"Undefined", "PCIe", "FCoE"}; + break; default: m = (typeof(m)){"Unknown", "", ""}; break; @@ -3950,7 +3958,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) int rc, i, hbq_count, buf_size, dma_buf_size, max_buf_size; uint8_t pn_page[LPFC_MAX_SUPPORTED_PAGES] = {0}; struct lpfc_mqe *mqe; - int longs; + int longs, sli_family; /* Before proceed, wait for POST done and device ready */ rc = lpfc_sli4_post_status_check(phba); @@ -4012,12 +4020,22 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) */ buf_size = (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp) + ((phba->cfg_sg_seg_cnt + 2) * sizeof(struct sli4_sge))); - /* Feature Level 1 hardware is limited to 2 pages */ - if ((bf_get(lpfc_sli_intf_featurelevel1, &phba->sli4_hba.sli_intf) == - LPFC_SLI_INTF_FEATURELEVEL1_1)) - max_buf_size = LPFC_SLI4_FL1_MAX_BUF_SIZE; - else - max_buf_size = LPFC_SLI4_MAX_BUF_SIZE; + + sli_family = bf_get(lpfc_sli_intf_sli_family, &phba->sli4_hba.sli_intf); + max_buf_size = LPFC_SLI4_MAX_BUF_SIZE; + switch (sli_family) { + case LPFC_SLI_INTF_FAMILY_BE2: + case LPFC_SLI_INTF_FAMILY_BE3: + /* There is a single hint for BE - 2 pages per BPL. */ + if (bf_get(lpfc_sli_intf_sli_hint1, &phba->sli4_hba.sli_intf) == + LPFC_SLI_INTF_SLI_HINT1_1) + max_buf_size = LPFC_SLI4_FL1_MAX_BUF_SIZE; + break; + case LPFC_SLI_INTF_FAMILY_LNCR_A0: + case LPFC_SLI_INTF_FAMILY_LNCR_B0: + default: + break; + } for (dma_buf_size = LPFC_SLI4_MIN_BUF_SIZE; dma_buf_size < max_buf_size && buf_size > dma_buf_size; dma_buf_size = dma_buf_size << 1) @@ -5233,16 +5251,22 @@ lpfc_sli4_post_status_check(struct lpfc_hba *phba) &phba->sli4_hba.sli_intf) == LPFC_SLI_INTF_VALID) { lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "2534 Device Info: ChipType=0x%x, SliRev=0x%x, " - "FeatureL1=0x%x, FeatureL2=0x%x\n", + "IFType=0x%x, SLIHint_1=0x%x, SLIHint_2=0x%x, " + "FT=0x%x\n", bf_get(lpfc_sli_intf_sli_family, &phba->sli4_hba.sli_intf), bf_get(lpfc_sli_intf_slirev, &phba->sli4_hba.sli_intf), - bf_get(lpfc_sli_intf_featurelevel1, + bf_get(lpfc_sli_intf_if_type, + &phba->sli4_hba.sli_intf), + bf_get(lpfc_sli_intf_sli_hint1, &phba->sli4_hba.sli_intf), - bf_get(lpfc_sli_intf_featurelevel2, + bf_get(lpfc_sli_intf_sli_hint2, + &phba->sli4_hba.sli_intf), + bf_get(lpfc_sli_intf_func_type, &phba->sli4_hba.sli_intf)); } + phba->sli4_hba.ue_mask_lo = readl(phba->sli4_hba.UEMASKLOregaddr); phba->sli4_hba.ue_mask_hi = readl(phba->sli4_hba.UEMASKHIregaddr); /* With uncoverable error, log the error message and return error */ @@ -8992,6 +9016,10 @@ static struct pci_device_id lpfc_id_table[] = { PCI_ANY_ID, PCI_ANY_ID, }, {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_BALIUS, PCI_ANY_ID, PCI_ANY_ID, }, + {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FC, + PCI_ANY_ID, PCI_ANY_ID, }, + {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FCOE, + PCI_ANY_ID, PCI_ANY_ID, }, { 0 } }; -- cgit v1.2.3-59-g8ed1b From 76a95d75ede64e4f1684ddb8c626fdfdb641bda2 Mon Sep 17 00:00:00 2001 From: James Smart Date: Sat, 20 Nov 2010 23:11:48 -0500 Subject: [SCSI] lpfc 8.3.19: Add SLI4 FC Discovery support Add SLI4 FC Discovery support - Replace READ_LA and READ_LA64 with READ_TOPOLOGY mailbox command. - Converted the old READ_LA structure to use bf_set/get instead of bit fields. - Rename HBA_FCOE_SUPPORT flag to HBA_FCOE_MODE. Flag now indicates function is running as SLI-4 FC or FCoE port. Make sure flag reset each time READ_REV completed as it can dynamically change. - Removed BDE union in the READ_TOPOLOGY mailbox command and added a define to define the ALPA MAP SIZE. Added FC Code for async events. - Added code to support new 16G link speed. - Define new set of values to keep track of valid user settable link speeds. - Used new link speed definitions to define link speed max and bitmap. - Redefined FDMI Port sppeds to be hax values and added the 16G value. - Added new CQE trailer code for FC Events. - Add lpfc_issue_init_vfi and lpfc_init_vfi_cmpl routines. - Replace many calls to the initial_flogi routine with lpfc_issue_init_vfi. - Add vp and vpi fields to the INIT_VFI mailbox command. - Addapt lpfc_hba_init_link routine for SLI4 use. - Use lpfc_hba_init_link call from lpfc_sli4_hba_setup. - Add a check for FC mode to register the FCFI before init link. - Convert lpfc_sli4_init_vpi to be called without a vpi (get it from vport). Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc.h | 19 +++- drivers/scsi/lpfc/lpfc_attr.c | 91 +++++++++--------- drivers/scsi/lpfc/lpfc_bsg.c | 5 +- drivers/scsi/lpfc/lpfc_crtn.h | 5 +- drivers/scsi/lpfc/lpfc_ct.c | 48 +++++----- drivers/scsi/lpfc/lpfc_els.c | 45 +++++---- drivers/scsi/lpfc/lpfc_hbadisc.c | 186 +++++++++++++++++++++++++----------- drivers/scsi/lpfc/lpfc_hw.h | 198 +++++++++++++++++++-------------------- drivers/scsi/lpfc/lpfc_hw4.h | 7 ++ drivers/scsi/lpfc/lpfc_init.c | 137 +++++++++++++++------------ drivers/scsi/lpfc/lpfc_mbox.c | 64 ++++++++----- drivers/scsi/lpfc/lpfc_sli.c | 81 ++++++++-------- drivers/scsi/lpfc/lpfc_sli4.h | 2 +- drivers/scsi/lpfc/lpfc_vport.c | 10 +- 14 files changed, 516 insertions(+), 382 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 196de40b906c..e86a0d2add3c 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -464,6 +464,23 @@ struct unsol_rcv_ct_ctx { #define UNSOL_VALID 0x00000001 }; +#define LPFC_USER_LINK_SPEED_AUTO 0 /* auto select (default)*/ +#define LPFC_USER_LINK_SPEED_1G 1 /* 1 Gigabaud */ +#define LPFC_USER_LINK_SPEED_2G 2 /* 2 Gigabaud */ +#define LPFC_USER_LINK_SPEED_4G 4 /* 4 Gigabaud */ +#define LPFC_USER_LINK_SPEED_8G 8 /* 8 Gigabaud */ +#define LPFC_USER_LINK_SPEED_10G 10 /* 10 Gigabaud */ +#define LPFC_USER_LINK_SPEED_16G 16 /* 16 Gigabaud */ +#define LPFC_USER_LINK_SPEED_MAX LPFC_USER_LINK_SPEED_16G +#define LPFC_USER_LINK_SPEED_BITMAP ((1 << LPFC_USER_LINK_SPEED_16G) | \ + (1 << LPFC_USER_LINK_SPEED_10G) | \ + (1 << LPFC_USER_LINK_SPEED_8G) | \ + (1 << LPFC_USER_LINK_SPEED_4G) | \ + (1 << LPFC_USER_LINK_SPEED_2G) | \ + (1 << LPFC_USER_LINK_SPEED_1G) | \ + (1 << LPFC_USER_LINK_SPEED_AUTO)) +#define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8, 10, 16" + struct lpfc_hba { /* SCSI interface function jump table entries */ int (*lpfc_new_scsi_buf) @@ -545,7 +562,7 @@ struct lpfc_hba { uint32_t hba_flag; /* hba generic flags */ #define HBA_ERATT_HANDLED 0x1 /* This flag is set when eratt handled */ #define DEFER_ERATT 0x2 /* Deferred error attention in progress */ -#define HBA_FCOE_SUPPORT 0x4 /* HBA function supports FCOE */ +#define HBA_FCOE_MODE 0x4 /* HBA function in FCoE Mode */ #define HBA_SP_QUEUE_EVT 0x8 /* Slow-path qevt posted to worker thread*/ #define HBA_POST_RECEIVE_BUFFER 0x10 /* Rcv buffers need to be posted */ #define FCP_XRI_ABORT_EVENT 0x20 diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index c1cbec01345d..45bd72a9f60e 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -52,10 +52,6 @@ #define LPFC_MIN_DEVLOSS_TMO 1 #define LPFC_MAX_DEVLOSS_TMO 255 -#define LPFC_MAX_LINK_SPEED 8 -#define LPFC_LINK_SPEED_BITMAP 0x00000117 -#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. @@ -463,7 +459,7 @@ lpfc_link_state_show(struct device *dev, struct device_attribute *attr, if (phba->sli.sli_flag & LPFC_MENLO_MAINT) len += snprintf(buf + len, PAGE_SIZE-len, " Menlo Maint Mode\n"); - else if (phba->fc_topology == TOPOLOGY_LOOP) { + else if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { if (vport->fc_flag & FC_PUBLIC_LOOP) len += snprintf(buf + len, PAGE_SIZE-len, " Public Loop\n"); @@ -2837,14 +2833,8 @@ static struct bin_attribute sysfs_drvr_stat_data_attr = { /* # lpfc_link_speed: Link speed selection for initializing the Fibre Channel # connection. -# 0 = auto select (default) -# 1 = 1 Gigabaud -# 2 = 2 Gigabaud -# 4 = 4 Gigabaud -# 8 = 8 Gigabaud -# Value range is [0,8]. Default value is 0. +# Value range is [0,16]. Default value is 0. */ - /** * lpfc_link_speed_set - Set the adapters link speed * @phba: lpfc_hba pointer. @@ -2869,7 +2859,7 @@ lpfc_link_speed_store(struct device *dev, struct device_attribute *attr, struct Scsi_Host *shost = class_to_shost(dev); struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; struct lpfc_hba *phba = vport->phba; - int val = 0; + int val = LPFC_USER_LINK_SPEED_AUTO; int nolip = 0; const char *val_buf = buf; int err; @@ -2885,15 +2875,20 @@ lpfc_link_speed_store(struct device *dev, struct device_attribute *attr, if (sscanf(val_buf, "%i", &val) != 1) return -EINVAL; - if (((val == LINK_SPEED_1G) && !(phba->lmt & LMT_1Gb)) || - ((val == LINK_SPEED_2G) && !(phba->lmt & LMT_2Gb)) || - ((val == LINK_SPEED_4G) && !(phba->lmt & LMT_4Gb)) || - ((val == LINK_SPEED_8G) && !(phba->lmt & LMT_8Gb)) || - ((val == LINK_SPEED_10G) && !(phba->lmt & LMT_10Gb))) + if (((val == LPFC_USER_LINK_SPEED_1G) && !(phba->lmt & LMT_1Gb)) || + ((val == LPFC_USER_LINK_SPEED_2G) && !(phba->lmt & LMT_2Gb)) || + ((val == LPFC_USER_LINK_SPEED_4G) && !(phba->lmt & LMT_4Gb)) || + ((val == LPFC_USER_LINK_SPEED_8G) && !(phba->lmt & LMT_8Gb)) || + ((val == LPFC_USER_LINK_SPEED_10G) && !(phba->lmt & LMT_10Gb)) || + ((val == LPFC_USER_LINK_SPEED_16G) && !(phba->lmt & LMT_16Gb))) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "2879 lpfc_link_speed attribute cannot be set " + "to %d. Speed is not supported by this port.\n", + val); return -EINVAL; - - if ((val >= 0 && val <= 8) - && (LPFC_LINK_SPEED_BITMAP & (1 << val))) { + } + if ((val >= 0) && (val <= LPFC_USER_LINK_SPEED_MAX) && + (LPFC_USER_LINK_SPEED_BITMAP & (1 << val))) { prev_val = phba->cfg_link_speed; phba->cfg_link_speed = val; if (nolip) @@ -2906,11 +2901,9 @@ lpfc_link_speed_store(struct device *dev, struct device_attribute *attr, } else return strlen(buf); } - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0469 lpfc_link_speed attribute cannot be set to %d, " - "allowed range is [0, 8]\n", - phba->brd_no, val); + "0469 lpfc_link_speed attribute cannot be set to %d, " + "allowed values are ["LPFC_LINK_SPEED_STRING"]\n", val); return -EINVAL; } @@ -2938,8 +2931,8 @@ lpfc_param_show(link_speed) static int lpfc_link_speed_init(struct lpfc_hba *phba, int val) { - if ((val >= 0 && val <= LPFC_MAX_LINK_SPEED) - && (LPFC_LINK_SPEED_BITMAP & (1 << val))) { + if ((val >= 0) && (val <= LPFC_USER_LINK_SPEED_MAX) && + (LPFC_USER_LINK_SPEED_BITMAP & (1 << val))) { phba->cfg_link_speed = val; return 0; } @@ -2947,12 +2940,12 @@ lpfc_link_speed_init(struct lpfc_hba *phba, int val) "0405 lpfc_link_speed attribute cannot " "be set to %d, allowed values are " "["LPFC_LINK_SPEED_STRING"]\n", val); - phba->cfg_link_speed = 0; + phba->cfg_link_speed = LPFC_USER_LINK_SPEED_AUTO; return -EINVAL; } static DEVICE_ATTR(lpfc_link_speed, S_IRUGO | S_IWUSR, - lpfc_link_speed_show, lpfc_link_speed_store); + lpfc_link_speed_show, lpfc_link_speed_store); /* # lpfc_aer_support: Support PCIe device Advanced Error Reporting (AER) @@ -3798,8 +3791,7 @@ sysfs_mbox_read(struct file *filp, struct kobject *kobj, } break; case MBX_READ_SPARM64: - case MBX_READ_LA: - case MBX_READ_LA64: + case MBX_READ_TOPOLOGY: case MBX_REG_LOGIN: case MBX_REG_LOGIN64: case MBX_CONFIG_PORT: @@ -3989,7 +3981,7 @@ lpfc_get_host_port_type(struct Scsi_Host *shost) if (vport->port_type == LPFC_NPIV_PORT) { fc_host_port_type(shost) = FC_PORTTYPE_NPIV; } else if (lpfc_is_link_up(phba)) { - if (phba->fc_topology == TOPOLOGY_LOOP) { + if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { if (vport->fc_flag & FC_PUBLIC_LOOP) fc_host_port_type(shost) = FC_PORTTYPE_NLPORT; else @@ -4058,23 +4050,26 @@ lpfc_get_host_speed(struct Scsi_Host *shost) if (lpfc_is_link_up(phba)) { switch(phba->fc_linkspeed) { - case LA_1GHZ_LINK: - fc_host_speed(shost) = FC_PORTSPEED_1GBIT; + case LPFC_LINK_SPEED_1GHZ: + fc_host_speed(shost) = FC_PORTSPEED_1GBIT; break; - case LA_2GHZ_LINK: - fc_host_speed(shost) = FC_PORTSPEED_2GBIT; + case LPFC_LINK_SPEED_2GHZ: + fc_host_speed(shost) = FC_PORTSPEED_2GBIT; break; - case LA_4GHZ_LINK: - fc_host_speed(shost) = FC_PORTSPEED_4GBIT; + case LPFC_LINK_SPEED_4GHZ: + fc_host_speed(shost) = FC_PORTSPEED_4GBIT; break; - case LA_8GHZ_LINK: - fc_host_speed(shost) = FC_PORTSPEED_8GBIT; + case LPFC_LINK_SPEED_8GHZ: + fc_host_speed(shost) = FC_PORTSPEED_8GBIT; break; - case LA_10GHZ_LINK: - fc_host_speed(shost) = FC_PORTSPEED_10GBIT; + case LPFC_LINK_SPEED_10GHZ: + fc_host_speed(shost) = FC_PORTSPEED_10GBIT; break; - default: - fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; + case LPFC_LINK_SPEED_16GHZ: + fc_host_speed(shost) = FC_PORTSPEED_16GBIT; + break; + default: + fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; break; } } else @@ -4097,7 +4092,7 @@ lpfc_get_host_fabric_name (struct Scsi_Host *shost) spin_lock_irq(shost->host_lock); if ((vport->fc_flag & FC_FABRIC) || - ((phba->fc_topology == TOPOLOGY_LOOP) && + ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) && (vport->fc_flag & FC_PUBLIC_LOOP))) node_name = wwn_to_u64(phba->fc_fabparam.nodeName.u.wwn); else @@ -4208,11 +4203,11 @@ lpfc_get_stats(struct Scsi_Host *shost) hs->invalid_crc_count -= lso->invalid_crc_count; hs->error_frames -= lso->error_frames; - if (phba->hba_flag & HBA_FCOE_SUPPORT) { + if (phba->hba_flag & HBA_FCOE_MODE) { hs->lip_count = -1; hs->nos_count = (phba->link_events >> 1); hs->nos_count -= lso->link_events; - } else if (phba->fc_topology == TOPOLOGY_LOOP) { + } else if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { hs->lip_count = (phba->fc_eventTag >> 1); hs->lip_count -= lso->link_events; hs->nos_count = -1; @@ -4303,7 +4298,7 @@ lpfc_reset_stats(struct Scsi_Host *shost) lso->invalid_tx_word_count = pmb->un.varRdLnk.invalidXmitWord; lso->invalid_crc_count = pmb->un.varRdLnk.crcCnt; lso->error_frames = pmb->un.varRdLnk.crcCnt; - if (phba->hba_flag & HBA_FCOE_SUPPORT) + if (phba->hba_flag & HBA_FCOE_MODE) lso->link_events = (phba->link_events >> 1); else lso->link_events = (phba->fc_eventTag >> 1); diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index c216f4eb0e37..50dbfc8018f6 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -2601,12 +2601,11 @@ static int lpfc_bsg_check_cmd_access(struct lpfc_hba *phba, phba->wait_4_mlo_maint_flg = 1; } else if (mb->un.varWords[0] == SETVAR_MLORST) { phba->link_flag &= ~LS_LOOPBACK_MODE; - phba->fc_topology = TOPOLOGY_PT_PT; + phba->fc_topology = LPFC_TOPOLOGY_PT_PT; } break; case MBX_READ_SPARM64: - case MBX_READ_LA: - case MBX_READ_LA64: + case MBX_READ_TOPOLOGY: case MBX_REG_LOGIN: case MBX_REG_LOGIN64: case MBX_CONFIG_PORT: diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index a5f5a093a8a4..1ea3075e3c5d 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -31,7 +31,7 @@ void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_config_async(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t); void lpfc_heart_beat(struct lpfc_hba *, LPFC_MBOXQ_t *); -int lpfc_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *, struct lpfc_dmabuf *); +int lpfc_read_topology(struct lpfc_hba *, LPFC_MBOXQ_t *, struct lpfc_dmabuf *); void lpfc_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_issue_clear_la(struct lpfc_hba *, struct lpfc_vport *); void lpfc_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *); @@ -64,7 +64,7 @@ void lpfc_cleanup_pending_mbox(struct lpfc_vport *); int lpfc_linkdown(struct lpfc_hba *); void lpfc_linkdown_port(struct lpfc_vport *); void lpfc_port_link_failure(struct lpfc_vport *); -void lpfc_mbx_cmpl_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *); +void lpfc_mbx_cmpl_read_topology(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_init_vpi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_cancel_all_vport_retry_delay_timer(struct lpfc_hba *); void lpfc_retry_pport_discovery(struct lpfc_hba *); @@ -121,6 +121,7 @@ void lpfc_end_rscn(struct lpfc_vport *); int lpfc_els_chk_latt(struct lpfc_vport *); int lpfc_els_abort_flogi(struct lpfc_hba *); int lpfc_initial_flogi(struct lpfc_vport *); +void lpfc_issue_init_vfi(struct lpfc_vport *); int lpfc_initial_fdisc(struct lpfc_vport *); int lpfc_issue_els_plogi(struct lpfc_vport *, uint32_t, uint8_t); int lpfc_issue_els_prli(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t); diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 463b74902ac4..c004fa9a681e 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -48,14 +48,14 @@ #include "lpfc_vport.h" #include "lpfc_debugfs.h" -#define HBA_PORTSPEED_UNKNOWN 0 /* Unknown - transceiver - * incapable of reporting */ -#define HBA_PORTSPEED_1GBIT 1 /* 1 GBit/sec */ -#define HBA_PORTSPEED_2GBIT 2 /* 2 GBit/sec */ -#define HBA_PORTSPEED_4GBIT 8 /* 4 GBit/sec */ -#define HBA_PORTSPEED_8GBIT 16 /* 8 GBit/sec */ -#define HBA_PORTSPEED_10GBIT 4 /* 10 GBit/sec */ -#define HBA_PORTSPEED_NOT_NEGOTIATED 5 /* Speed not established */ +/* FDMI Port Speed definitions */ +#define HBA_PORTSPEED_1GBIT 0x0001 /* 1 GBit/sec */ +#define HBA_PORTSPEED_2GBIT 0x0002 /* 2 GBit/sec */ +#define HBA_PORTSPEED_4GBIT 0x0008 /* 4 GBit/sec */ +#define HBA_PORTSPEED_10GBIT 0x0004 /* 10 GBit/sec */ +#define HBA_PORTSPEED_8GBIT 0x0010 /* 8 GBit/sec */ +#define HBA_PORTSPEED_16GBIT 0x0020 /* 16 GBit/sec */ +#define HBA_PORTSPEED_UNKNOWN 0x0800 /* Unknown */ #define FOURBYTES 4 @@ -1593,8 +1593,10 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode) ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + 4); ae->un.SupportSpeed = 0; + if (phba->lmt & LMT_16Gb) + ae->un.SupportSpeed |= HBA_PORTSPEED_16GBIT; if (phba->lmt & LMT_10Gb) - ae->un.SupportSpeed = HBA_PORTSPEED_10GBIT; + ae->un.SupportSpeed |= HBA_PORTSPEED_10GBIT; if (phba->lmt & LMT_8Gb) ae->un.SupportSpeed |= HBA_PORTSPEED_8GBIT; if (phba->lmt & LMT_4Gb) @@ -1612,24 +1614,26 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode) ae->ad.bits.AttrType = be16_to_cpu(PORT_SPEED); ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + 4); switch(phba->fc_linkspeed) { - case LA_1GHZ_LINK: - ae->un.PortSpeed = HBA_PORTSPEED_1GBIT; + case LPFC_LINK_SPEED_1GHZ: + ae->un.PortSpeed = HBA_PORTSPEED_1GBIT; break; - case LA_2GHZ_LINK: - ae->un.PortSpeed = HBA_PORTSPEED_2GBIT; + case LPFC_LINK_SPEED_2GHZ: + ae->un.PortSpeed = HBA_PORTSPEED_2GBIT; break; - case LA_4GHZ_LINK: - ae->un.PortSpeed = HBA_PORTSPEED_4GBIT; + case LPFC_LINK_SPEED_4GHZ: + ae->un.PortSpeed = HBA_PORTSPEED_4GBIT; break; - case LA_8GHZ_LINK: - ae->un.PortSpeed = HBA_PORTSPEED_8GBIT; + case LPFC_LINK_SPEED_8GHZ: + ae->un.PortSpeed = HBA_PORTSPEED_8GBIT; break; - case LA_10GHZ_LINK: - ae->un.PortSpeed = HBA_PORTSPEED_10GBIT; + case LPFC_LINK_SPEED_10GHZ: + ae->un.PortSpeed = HBA_PORTSPEED_10GBIT; break; - default: - ae->un.PortSpeed = - HBA_PORTSPEED_UNKNOWN; + case LPFC_LINK_SPEED_16GHZ: + ae->un.PortSpeed = HBA_PORTSPEED_16GBIT; + break; + default: + ae->un.PortSpeed = HBA_PORTSPEED_UNKNOWN; break; } pab->ab.EntryCnt++; diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 196a7bf905a1..04072ce9c905 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -523,7 +523,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, phba->fc_edtovResol = sp->cmn.edtovResolution; phba->fc_ratov = (be32_to_cpu(sp->cmn.w2.r_a_tov) + 999) / 1000; - if (phba->fc_topology == TOPOLOGY_LOOP) { + if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { spin_lock_irq(shost->host_lock); vport->fc_flag |= FC_PUBLIC_LOOP; spin_unlock_irq(shost->host_lock); @@ -832,6 +832,12 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, if (lpfc_els_retry(phba, cmdiocb, rspiocb)) goto out; + /* FLOGI failure */ + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0100 FLOGI failure Status:x%x/x%x TMO:x%x\n", + irsp->ulpStatus, irsp->un.ulpWord[4], + irsp->ulpTimeout); + /* FLOGI failed, so there is no fabric */ spin_lock_irq(shost->host_lock); vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); @@ -843,13 +849,16 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, */ if (phba->alpa_map[0] == 0) { vport->cfg_discovery_threads = LPFC_MAX_DISC_THREADS; + if ((phba->sli_rev == LPFC_SLI_REV4) && + (!(vport->fc_flag & FC_VFI_REGISTERED) || + (vport->fc_prevDID != vport->fc_myDID))) { + if (vport->fc_flag & FC_VFI_REGISTERED) + lpfc_sli4_unreg_all_rpis(vport); + lpfc_issue_reg_vfi(vport); + lpfc_nlp_put(ndlp); + goto out; + } } - - /* FLOGI failure */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, - "0100 FLOGI failure Status:x%x/x%x TMO:x%x\n", - irsp->ulpStatus, irsp->un.ulpWord[4], - irsp->ulpTimeout); goto flogifail; } spin_lock_irq(shost->host_lock); @@ -879,7 +888,7 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, */ if (sp->cmn.fPort) rc = lpfc_cmpl_els_flogi_fabric(vport, ndlp, sp, irsp); - else if (!(phba->hba_flag & HBA_FCOE_SUPPORT)) + else if (!(phba->hba_flag & HBA_FCOE_MODE)) rc = lpfc_cmpl_els_flogi_nport(vport, ndlp, sp); else { lpfc_printf_vlog(vport, KERN_ERR, @@ -1027,7 +1036,7 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, icmd->ulpCt_l = 0; } - if (phba->fc_topology != TOPOLOGY_LOOP) { + if (phba->fc_topology != LPFC_TOPOLOGY_LOOP) { icmd->un.elsreq64.myID = 0; icmd->un.elsreq64.fl = 1; } @@ -2722,7 +2731,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, if (cmd == ELS_CMD_FLOGI) { if (PCI_DEVICE_ID_HORNET == phba->pcidev->device) { - phba->fc_topology = TOPOLOGY_LOOP; + phba->fc_topology = LPFC_TOPOLOGY_LOOP; phba->pport->fc_myDID = 0; phba->alpa_map[0] = 0; phba->alpa_map[1] = 0; @@ -2877,7 +2886,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, retry = 1; if (((cmd == ELS_CMD_FLOGI) || (cmd == ELS_CMD_FDISC)) && - (phba->fc_topology != TOPOLOGY_LOOP) && + (phba->fc_topology != LPFC_TOPOLOGY_LOOP) && !lpfc_error_lost_link(irsp)) { /* FLOGI retry policy */ retry = 1; @@ -4597,7 +4606,7 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, lpfc_set_disctmo(vport); - if (phba->fc_topology == TOPOLOGY_LOOP) { + if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { /* We should never receive a FLOGI in loop mode, ignore it */ did = icmd->un.elsreq64.remoteID; @@ -4940,7 +4949,7 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) pcmd += sizeof(uint32_t); /* Skip past command */ rps_rsp = (RPS_RSP *)pcmd; - if (phba->fc_topology != TOPOLOGY_LOOP) + if (phba->fc_topology != LPFC_TOPOLOGY_LOOP) status = 0x10; else status = 0x8; @@ -5482,7 +5491,7 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, (memcmp(&phba->fc_fabparam.portName, &fp->FportName, sizeof(struct lpfc_name)))) { /* This port has switched fabrics. FLOGI is required */ - lpfc_initial_flogi(vport); + lpfc_issue_init_vfi(vport); } else { /* FAN verified - skip FLOGI */ vport->fc_myDID = vport->fc_prevDID; @@ -6373,7 +6382,7 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport) if (!ndlp) { ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); if (!ndlp) { - if (phba->fc_topology == TOPOLOGY_LOOP) { + if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { lpfc_disc_start(vport); return; } @@ -6386,7 +6395,7 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport) } else if (!NLP_CHK_NODE_ACT(ndlp)) { ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE); if (!ndlp) { - if (phba->fc_topology == TOPOLOGY_LOOP) { + if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { lpfc_disc_start(vport); return; } @@ -6510,7 +6519,7 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) spin_unlock_irq(shost->host_lock); if (vport->port_type == LPFC_PHYSICAL_PORT && !(vport->fc_flag & FC_LOGO_RCVD_DID_CHNG)) - lpfc_initial_flogi(vport); + lpfc_issue_init_vfi(vport); else lpfc_initial_fdisc(vport); break; @@ -6747,7 +6756,7 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, vport->fc_flag &= ~FC_VPORT_CVL_RCVD; vport->fc_flag &= ~FC_VPORT_LOGO_RCVD; vport->fc_flag |= FC_FABRIC; - if (vport->phba->fc_topology == TOPOLOGY_LOOP) + if (vport->phba->fc_topology == LPFC_TOPOLOGY_LOOP) vport->fc_flag |= FC_PUBLIC_LOOP; spin_unlock_irq(shost->host_lock); diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 57ab799da2e2..e8d27c958510 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1064,7 +1064,7 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) mempool_free(pmb, phba->mbox_mem_pool); - if (phba->fc_topology == TOPOLOGY_LOOP && + if (phba->fc_topology == LPFC_TOPOLOGY_LOOP && vport->fc_flag & FC_PUBLIC_LOOP && !(vport->fc_flag & FC_LBIT)) { /* Need to wait for FAN - use discovery timer @@ -1078,9 +1078,8 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) /* Start discovery by sending a FLOGI. port_state is identically * LPFC_FLOGI while waiting for FLOGI cmpl */ - if (vport->port_state != LPFC_FLOGI) { + if (vport->port_state != LPFC_FLOGI) lpfc_initial_flogi(vport); - } return; out: @@ -1131,7 +1130,7 @@ lpfc_mbx_cmpl_reg_fcfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) if (vport->port_state != LPFC_FLOGI) { phba->hba_flag |= FCF_RR_INPROG; spin_unlock_irq(&phba->hbalock); - lpfc_initial_flogi(vport); + lpfc_issue_init_vfi(vport); goto out; } spin_unlock_irq(&phba->hbalock); @@ -1353,7 +1352,7 @@ lpfc_register_fcf(struct lpfc_hba *phba) if (phba->pport->port_state != LPFC_FLOGI) { phba->hba_flag |= FCF_RR_INPROG; spin_unlock_irq(&phba->hbalock); - lpfc_initial_flogi(phba->pport); + lpfc_issue_init_vfi(phba->pport); return; } spin_unlock_irq(&phba->hbalock); @@ -2331,7 +2330,7 @@ lpfc_mbx_cmpl_fcf_rr_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) phba->fcf.current_rec.fcf_indx, fcf_index); /* Wait 500 ms before retrying FLOGI to current FCF */ msleep(500); - lpfc_initial_flogi(phba->pport); + lpfc_issue_init_vfi(phba->pport); goto out; } @@ -2421,6 +2420,63 @@ out: lpfc_sli4_mbox_cmd_free(phba, mboxq); } +/** + * lpfc_init_vfi_cmpl - Completion handler for init_vfi mbox command. + * @phba: pointer to lpfc hba data structure. + * @mboxq: pointer to mailbox data structure. + * + * This function handles completion of init vfi mailbox command. + */ +void +lpfc_init_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) +{ + struct lpfc_vport *vport = mboxq->vport; + + if (mboxq->u.mb.mbxStatus && (mboxq->u.mb.mbxStatus != 0x4002)) { + lpfc_printf_vlog(vport, KERN_ERR, + LOG_MBOX, + "2891 Init VFI mailbox failed 0x%x\n", + mboxq->u.mb.mbxStatus); + mempool_free(mboxq, phba->mbox_mem_pool); + lpfc_vport_set_state(vport, FC_VPORT_FAILED); + return; + } + lpfc_initial_flogi(vport); + mempool_free(mboxq, phba->mbox_mem_pool); + return; +} + +/** + * lpfc_issue_init_vfi - Issue init_vfi mailbox command. + * @vport: pointer to lpfc_vport data structure. + * + * This function issue a init_vfi mailbox command to initialize the VFI and + * VPI for the physical port. + */ +void +lpfc_issue_init_vfi(struct lpfc_vport *vport) +{ + LPFC_MBOXQ_t *mboxq; + int rc; + struct lpfc_hba *phba = vport->phba; + + mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); + if (!mboxq) { + lpfc_printf_vlog(vport, KERN_ERR, + LOG_MBOX, "2892 Failed to allocate " + "init_vfi mailbox\n"); + return; + } + lpfc_init_vfi(mboxq, vport); + mboxq->mbox_cmpl = lpfc_init_vfi_cmpl; + rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT); + if (rc == MBX_NOT_FINISHED) { + lpfc_printf_vlog(vport, KERN_ERR, + LOG_MBOX, "2893 Failed to issue init_vfi mailbox\n"); + mempool_free(mboxq, vport->phba->mbox_mem_pool); + } +} + /** * lpfc_init_vpi_cmpl - Completion handler for init_vpi mbox command. * @phba: pointer to lpfc hba data structure. @@ -2528,7 +2584,7 @@ lpfc_start_fdiscs(struct lpfc_hba *phba) FC_VPORT_FAILED); continue; } - if (phba->fc_topology == TOPOLOGY_LOOP) { + if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { lpfc_vport_set_state(vports[i], FC_VPORT_LINKDOWN); continue; @@ -2564,7 +2620,7 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) "2018 REG_VFI mbxStatus error x%x " "HBA state x%x\n", mboxq->u.mb.mbxStatus, vport->port_state); - if (phba->fc_topology == TOPOLOGY_LOOP) { + if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { /* FLOGI failed, use loop map to make discovery list */ lpfc_disc_list_loopmap(vport); /* Start discovery */ @@ -2582,8 +2638,18 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) spin_unlock_irq(shost->host_lock); if (vport->port_state == LPFC_FABRIC_CFG_LINK) { - lpfc_start_fdiscs(phba); - lpfc_do_scr_ns_plogi(phba, vport); + /* For private loop just start discovery and we are done. */ + if ((phba->fc_topology == LPFC_TOPOLOGY_LOOP) && + (phba->alpa_map[0] == 0) && + !(vport->fc_flag & FC_PUBLIC_LOOP)) { + /* Use loop map to make discovery list */ + lpfc_disc_list_loopmap(vport); + /* Start discovery */ + lpfc_disc_start(vport); + } else { + lpfc_start_fdiscs(phba); + lpfc_do_scr_ns_plogi(phba, vport); + } } fail_free_mem: @@ -2644,7 +2710,7 @@ out: } static void -lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) +lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) { struct lpfc_vport *vport = phba->pport; LPFC_MBOXQ_t *sparam_mbox, *cfglink_mbox = NULL; @@ -2654,31 +2720,24 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) struct fcf_record *fcf_record; spin_lock_irq(&phba->hbalock); - switch (la->UlnkSpeed) { - case LA_1GHZ_LINK: - phba->fc_linkspeed = LA_1GHZ_LINK; - break; - case LA_2GHZ_LINK: - phba->fc_linkspeed = LA_2GHZ_LINK; - break; - case LA_4GHZ_LINK: - phba->fc_linkspeed = LA_4GHZ_LINK; - break; - case LA_8GHZ_LINK: - phba->fc_linkspeed = LA_8GHZ_LINK; - break; - case LA_10GHZ_LINK: - phba->fc_linkspeed = LA_10GHZ_LINK; + switch (bf_get(lpfc_mbx_read_top_link_spd, la)) { + case LPFC_LINK_SPEED_1GHZ: + case LPFC_LINK_SPEED_2GHZ: + case LPFC_LINK_SPEED_4GHZ: + case LPFC_LINK_SPEED_8GHZ: + case LPFC_LINK_SPEED_10GHZ: + case LPFC_LINK_SPEED_16GHZ: + phba->fc_linkspeed = bf_get(lpfc_mbx_read_top_link_spd, la); break; default: - phba->fc_linkspeed = LA_UNKNW_LINK; + phba->fc_linkspeed = LPFC_LINK_SPEED_UNKNOWN; break; } - phba->fc_topology = la->topology; + phba->fc_topology = bf_get(lpfc_mbx_read_top_topology, la); phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED; - if (phba->fc_topology == TOPOLOGY_LOOP) { + if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { phba->sli3_options &= ~LPFC_SLI3_NPIV_ENABLED; /* if npiv is enabled and this adapter supports npiv log @@ -2689,11 +2748,11 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) "1309 Link Up Event npiv not supported in loop " "topology\n"); /* Get Loop Map information */ - if (la->il) + if (bf_get(lpfc_mbx_read_top_il, la)) vport->fc_flag |= FC_LBIT; - vport->fc_myDID = la->granted_AL_PA; - i = la->un.lilpBde64.tus.f.bdeSize; + vport->fc_myDID = bf_get(lpfc_mbx_read_top_alpa_granted, la); + i = la->lilpBde64.tus.f.bdeSize; if (i == 0) { phba->alpa_map[0] = 0; @@ -2764,7 +2823,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) goto out; } - if (!(phba->hba_flag & HBA_FCOE_SUPPORT)) { + if (!(phba->hba_flag & HBA_FCOE_MODE)) { cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!cfglink_mbox) goto out; @@ -2874,17 +2933,17 @@ lpfc_mbx_issue_link_down(struct lpfc_hba *phba) /* - * This routine handles processing a READ_LA mailbox + * This routine handles processing a READ_TOPOLOGY mailbox * command upon completion. It is setup in the LPFC_MBOXQ * as the completion routine when the command is * handed off to the SLI layer. */ void -lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) +lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) { struct lpfc_vport *vport = pmb->vport; struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - READ_LA_VAR *la; + struct lpfc_mbx_read_top *la; MAILBOX_t *mb = &pmb->u.mb; struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1); @@ -2897,15 +2956,15 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) mb->mbxStatus, vport->port_state); lpfc_mbx_issue_link_down(phba); phba->link_state = LPFC_HBA_ERROR; - goto lpfc_mbx_cmpl_read_la_free_mbuf; + goto lpfc_mbx_cmpl_read_topology_free_mbuf; } - la = (READ_LA_VAR *) &pmb->u.mb.un.varReadLA; + la = (struct lpfc_mbx_read_top *) &pmb->u.mb.un.varReadTop; memcpy(&phba->alpa_map[0], mp->virt, 128); spin_lock_irq(shost->host_lock); - if (la->pb) + if (bf_get(lpfc_mbx_read_top_pb, la)) vport->fc_flag |= FC_BYPASSED_MODE; else vport->fc_flag &= ~FC_BYPASSED_MODE; @@ -2914,41 +2973,48 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) if ((phba->fc_eventTag < la->eventTag) || (phba->fc_eventTag == la->eventTag)) { phba->fc_stat.LinkMultiEvent++; - if (la->attType == AT_LINK_UP) + if (bf_get(lpfc_mbx_read_top_att_type, la) == LPFC_ATT_LINK_UP) if (phba->fc_eventTag != 0) lpfc_linkdown(phba); } phba->fc_eventTag = la->eventTag; spin_lock_irq(&phba->hbalock); - if (la->mm) + if (bf_get(lpfc_mbx_read_top_mm, la)) phba->sli.sli_flag |= LPFC_MENLO_MAINT; else phba->sli.sli_flag &= ~LPFC_MENLO_MAINT; spin_unlock_irq(&phba->hbalock); phba->link_events++; - if (la->attType == AT_LINK_UP && (!la->mm)) { + if ((bf_get(lpfc_mbx_read_top_att_type, la) == LPFC_ATT_LINK_UP) && + (!bf_get(lpfc_mbx_read_top_mm, la))) { phba->fc_stat.LinkUp++; if (phba->link_flag & LS_LOOPBACK_MODE) { lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, "1306 Link Up Event in loop back mode " "x%x received Data: x%x x%x x%x x%x\n", la->eventTag, phba->fc_eventTag, - la->granted_AL_PA, la->UlnkSpeed, + bf_get(lpfc_mbx_read_top_alpa_granted, + la), + bf_get(lpfc_mbx_read_top_link_spd, la), phba->alpa_map[0]); } else { lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, "1303 Link Up Event x%x received " "Data: x%x x%x x%x x%x x%x x%x %d\n", la->eventTag, phba->fc_eventTag, - la->granted_AL_PA, la->UlnkSpeed, + bf_get(lpfc_mbx_read_top_alpa_granted, + la), + bf_get(lpfc_mbx_read_top_link_spd, la), phba->alpa_map[0], - la->mm, la->fa, + bf_get(lpfc_mbx_read_top_mm, la), + bf_get(lpfc_mbx_read_top_fa, la), phba->wait_4_mlo_maint_flg); } lpfc_mbx_process_link_up(phba, la); - } else if (la->attType == AT_LINK_DOWN) { + } else if (bf_get(lpfc_mbx_read_top_att_type, la) == + LPFC_ATT_LINK_DOWN) { phba->fc_stat.LinkDown++; if (phba->link_flag & LS_LOOPBACK_MODE) { lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, @@ -2964,11 +3030,13 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) "Data: x%x x%x x%x x%x x%x\n", la->eventTag, phba->fc_eventTag, phba->pport->port_state, vport->fc_flag, - la->mm, la->fa); + bf_get(lpfc_mbx_read_top_mm, la), + bf_get(lpfc_mbx_read_top_fa, la)); } lpfc_mbx_issue_link_down(phba); } - if (la->mm && la->attType == AT_LINK_UP) { + if ((bf_get(lpfc_mbx_read_top_mm, la)) && + (bf_get(lpfc_mbx_read_top_att_type, la) == LPFC_ATT_LINK_UP)) { if (phba->link_state != LPFC_LINK_DOWN) { phba->fc_stat.LinkDown++; lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, @@ -2996,14 +3064,15 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) } } - if (la->fa) { - if (la->mm) + if (bf_get(lpfc_mbx_read_top_fa, la)) { + if (bf_get(lpfc_mbx_read_top_mm, la)) lpfc_issue_clear_la(phba, vport); lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, - "1311 fa %d\n", la->fa); + "1311 fa %d\n", + bf_get(lpfc_mbx_read_top_fa, la)); } -lpfc_mbx_cmpl_read_la_free_mbuf: +lpfc_mbx_cmpl_read_topology_free_mbuf: lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); mempool_free(pmb, phba->mbox_mem_pool); @@ -3333,7 +3402,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) kfree(mp); mempool_free(pmb, phba->mbox_mem_pool); - if (phba->fc_topology == TOPOLOGY_LOOP) { + if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { /* FLOGI failed, use loop map to make discovery list */ lpfc_disc_list_loopmap(vport); @@ -3413,7 +3482,7 @@ out: /* If no other thread is using the ndlp, free it */ lpfc_nlp_not_used(ndlp); - if (phba->fc_topology == TOPOLOGY_LOOP) { + if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { /* * RegLogin failed, use loop map to make discovery * list @@ -4441,7 +4510,7 @@ lpfc_disc_list_loopmap(struct lpfc_vport *vport) if (!lpfc_is_link_up(phba)) return; - if (phba->fc_topology != TOPOLOGY_LOOP) + if (phba->fc_topology != LPFC_TOPOLOGY_LOOP) return; /* Check for loop map present or not */ @@ -4793,7 +4862,10 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) } } if (vport->port_state != LPFC_FLOGI) { - lpfc_initial_flogi(vport); + if (phba->sli_rev <= LPFC_SLI_REV3) + lpfc_initial_flogi(vport); + else + lpfc_issue_init_vfi(vport); return; } break; @@ -5559,7 +5631,7 @@ lpfc_unregister_unused_fcf(struct lpfc_hba *phba) * registered, do nothing. */ spin_lock_irq(&phba->hbalock); - if (!(phba->hba_flag & HBA_FCOE_SUPPORT) || + if (!(phba->hba_flag & HBA_FCOE_MODE) || !(phba->fcf.fcf_flag & FCF_REGISTERED) || !(phba->hba_flag & HBA_FIP_SUPPORT) || (phba->fcf.fcf_flag & FCF_DISCOVERY) || diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 1044c438bb95..a253216e1f18 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -1370,7 +1370,6 @@ typedef struct { /* FireFly BIU registers */ #define MBX_READ_LNK_STAT 0x12 #define MBX_REG_LOGIN 0x13 #define MBX_UNREG_LOGIN 0x14 -#define MBX_READ_LA 0x15 #define MBX_CLEAR_LA 0x16 #define MBX_DUMP_MEMORY 0x17 #define MBX_DUMP_CONTEXT 0x18 @@ -1404,7 +1403,7 @@ typedef struct { /* FireFly BIU registers */ #define MBX_READ_SPARM64 0x8D #define MBX_READ_RPI64 0x8F #define MBX_REG_LOGIN64 0x93 -#define MBX_READ_LA64 0x95 +#define MBX_READ_TOPOLOGY 0x95 #define MBX_REG_VPI 0x96 #define MBX_UNREG_VPI 0x97 @@ -1825,12 +1824,13 @@ typedef struct { #define FLAGS_IMED_ABORT 0x04000 /* Bit 14 */ uint32_t link_speed; -#define LINK_SPEED_AUTO 0 /* Auto selection */ -#define LINK_SPEED_1G 1 /* 1 Gigabaud */ -#define LINK_SPEED_2G 2 /* 2 Gigabaud */ -#define LINK_SPEED_4G 4 /* 4 Gigabaud */ -#define LINK_SPEED_8G 8 /* 8 Gigabaud */ -#define LINK_SPEED_10G 16 /* 10 Gigabaud */ +#define LINK_SPEED_AUTO 0x0 /* Auto selection */ +#define LINK_SPEED_1G 0x1 /* 1 Gigabaud */ +#define LINK_SPEED_2G 0x2 /* 2 Gigabaud */ +#define LINK_SPEED_4G 0x4 /* 4 Gigabaud */ +#define LINK_SPEED_8G 0x8 /* 8 Gigabaud */ +#define LINK_SPEED_10G 0x10 /* 10 Gigabaud */ +#define LINK_SPEED_16G 0x11 /* 16 Gigabaud */ } INIT_LINK_VAR; @@ -2001,6 +2001,7 @@ typedef struct { #define LMT_4Gb 0x040 #define LMT_8Gb 0x080 #define LMT_10Gb 0x100 +#define LMT_16Gb 0x200 uint32_t rsvd2; uint32_t rsvd3; uint32_t max_xri; @@ -2396,100 +2397,93 @@ typedef struct { #endif } UNREG_D_ID_VAR; -/* Structure for MB Command READ_LA (21) */ -/* Structure for MB Command READ_LA64 (0x95) */ - -typedef struct { +/* Structure for MB Command READ_TOPOLOGY (0x95) */ +struct lpfc_mbx_read_top { uint32_t eventTag; /* Event tag */ -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t rsvd1:19; - uint32_t fa:1; - uint32_t mm:1; /* Menlo Maintenance mode enabled */ - uint32_t rx:1; - uint32_t pb:1; - uint32_t il:1; - uint32_t attType:8; -#else /* __LITTLE_ENDIAN_BITFIELD */ - uint32_t attType:8; - uint32_t il:1; - uint32_t pb:1; - uint32_t rx:1; - uint32_t mm:1; - uint32_t fa:1; - uint32_t rsvd1:19; -#endif - -#define AT_RESERVED 0x00 /* Reserved - attType */ -#define AT_LINK_UP 0x01 /* Link is up */ -#define AT_LINK_DOWN 0x02 /* Link is down */ - -#ifdef __BIG_ENDIAN_BITFIELD - uint8_t granted_AL_PA; - uint8_t lipAlPs; - uint8_t lipType; - uint8_t topology; -#else /* __LITTLE_ENDIAN_BITFIELD */ - uint8_t topology; - uint8_t lipType; - uint8_t lipAlPs; - uint8_t granted_AL_PA; -#endif - -#define TOPOLOGY_PT_PT 0x01 /* Topology is pt-pt / pt-fabric */ -#define TOPOLOGY_LOOP 0x02 /* Topology is FC-AL */ -#define TOPOLOGY_LNK_MENLO_MAINTENANCE 0x05 /* maint mode zephtr to menlo */ - - union { - struct ulp_bde lilpBde; /* This BDE points to a 128 byte buffer - to */ - /* store the LILP AL_PA position map into */ - struct ulp_bde64 lilpBde64; - } un; - -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t Dlu:1; - uint32_t Dtf:1; - uint32_t Drsvd2:14; - uint32_t DlnkSpeed:8; - uint32_t DnlPort:4; - uint32_t Dtx:2; - uint32_t Drx:2; -#else /* __LITTLE_ENDIAN_BITFIELD */ - uint32_t Drx:2; - uint32_t Dtx:2; - uint32_t DnlPort:4; - uint32_t DlnkSpeed:8; - uint32_t Drsvd2:14; - uint32_t Dtf:1; - uint32_t Dlu:1; -#endif - -#ifdef __BIG_ENDIAN_BITFIELD - uint32_t Ulu:1; - uint32_t Utf:1; - uint32_t Ursvd2:14; - uint32_t UlnkSpeed:8; - uint32_t UnlPort:4; - uint32_t Utx:2; - uint32_t Urx:2; -#else /* __LITTLE_ENDIAN_BITFIELD */ - uint32_t Urx:2; - uint32_t Utx:2; - uint32_t UnlPort:4; - uint32_t UlnkSpeed:8; - uint32_t Ursvd2:14; - uint32_t Utf:1; - uint32_t Ulu:1; -#endif - -#define LA_UNKNW_LINK 0x0 /* lnkSpeed */ -#define LA_1GHZ_LINK 0x04 /* lnkSpeed */ -#define LA_2GHZ_LINK 0x08 /* lnkSpeed */ -#define LA_4GHZ_LINK 0x10 /* lnkSpeed */ -#define LA_8GHZ_LINK 0x20 /* lnkSpeed */ -#define LA_10GHZ_LINK 0x40 /* lnkSpeed */ - -} READ_LA_VAR; + uint32_t word2; +#define lpfc_mbx_read_top_fa_SHIFT 12 +#define lpfc_mbx_read_top_fa_MASK 0x00000001 +#define lpfc_mbx_read_top_fa_WORD word2 +#define lpfc_mbx_read_top_mm_SHIFT 11 +#define lpfc_mbx_read_top_mm_MASK 0x00000001 +#define lpfc_mbx_read_top_mm_WORD word2 +#define lpfc_mbx_read_top_pb_SHIFT 9 +#define lpfc_mbx_read_top_pb_MASK 0X00000001 +#define lpfc_mbx_read_top_pb_WORD word2 +#define lpfc_mbx_read_top_il_SHIFT 8 +#define lpfc_mbx_read_top_il_MASK 0x00000001 +#define lpfc_mbx_read_top_il_WORD word2 +#define lpfc_mbx_read_top_att_type_SHIFT 0 +#define lpfc_mbx_read_top_att_type_MASK 0x000000FF +#define lpfc_mbx_read_top_att_type_WORD word2 +#define LPFC_ATT_RESERVED 0x00 /* Reserved - attType */ +#define LPFC_ATT_LINK_UP 0x01 /* Link is up */ +#define LPFC_ATT_LINK_DOWN 0x02 /* Link is down */ + uint32_t word3; +#define lpfc_mbx_read_top_alpa_granted_SHIFT 24 +#define lpfc_mbx_read_top_alpa_granted_MASK 0x000000FF +#define lpfc_mbx_read_top_alpa_granted_WORD word3 +#define lpfc_mbx_read_top_lip_alps_SHIFT 16 +#define lpfc_mbx_read_top_lip_alps_MASK 0x000000FF +#define lpfc_mbx_read_top_lip_alps_WORD word3 +#define lpfc_mbx_read_top_lip_type_SHIFT 8 +#define lpfc_mbx_read_top_lip_type_MASK 0x000000FF +#define lpfc_mbx_read_top_lip_type_WORD word3 +#define lpfc_mbx_read_top_topology_SHIFT 0 +#define lpfc_mbx_read_top_topology_MASK 0x000000FF +#define lpfc_mbx_read_top_topology_WORD word3 +#define LPFC_TOPOLOGY_PT_PT 0x01 /* Topology is pt-pt / pt-fabric */ +#define LPFC_TOPOLOGY_LOOP 0x02 /* Topology is FC-AL */ +#define LPFC_TOPOLOGY_MM 0x05 /* maint mode zephtr to menlo */ + /* store the LILP AL_PA position map into */ + struct ulp_bde64 lilpBde64; +#define LPFC_ALPA_MAP_SIZE 128 + uint32_t word7; +#define lpfc_mbx_read_top_ld_lu_SHIFT 31 +#define lpfc_mbx_read_top_ld_lu_MASK 0x00000001 +#define lpfc_mbx_read_top_ld_lu_WORD word7 +#define lpfc_mbx_read_top_ld_tf_SHIFT 30 +#define lpfc_mbx_read_top_ld_tf_MASK 0x00000001 +#define lpfc_mbx_read_top_ld_tf_WORD word7 +#define lpfc_mbx_read_top_ld_link_spd_SHIFT 8 +#define lpfc_mbx_read_top_ld_link_spd_MASK 0x000000FF +#define lpfc_mbx_read_top_ld_link_spd_WORD word7 +#define lpfc_mbx_read_top_ld_nl_port_SHIFT 4 +#define lpfc_mbx_read_top_ld_nl_port_MASK 0x0000000F +#define lpfc_mbx_read_top_ld_nl_port_WORD word7 +#define lpfc_mbx_read_top_ld_tx_SHIFT 2 +#define lpfc_mbx_read_top_ld_tx_MASK 0x00000003 +#define lpfc_mbx_read_top_ld_tx_WORD word7 +#define lpfc_mbx_read_top_ld_rx_SHIFT 0 +#define lpfc_mbx_read_top_ld_rx_MASK 0x00000003 +#define lpfc_mbx_read_top_ld_rx_WORD word7 + uint32_t word8; +#define lpfc_mbx_read_top_lu_SHIFT 31 +#define lpfc_mbx_read_top_lu_MASK 0x00000001 +#define lpfc_mbx_read_top_lu_WORD word8 +#define lpfc_mbx_read_top_tf_SHIFT 30 +#define lpfc_mbx_read_top_tf_MASK 0x00000001 +#define lpfc_mbx_read_top_tf_WORD word8 +#define lpfc_mbx_read_top_link_spd_SHIFT 8 +#define lpfc_mbx_read_top_link_spd_MASK 0x000000FF +#define lpfc_mbx_read_top_link_spd_WORD word8 +#define lpfc_mbx_read_top_nl_port_SHIFT 4 +#define lpfc_mbx_read_top_nl_port_MASK 0x0000000F +#define lpfc_mbx_read_top_nl_port_WORD word8 +#define lpfc_mbx_read_top_tx_SHIFT 2 +#define lpfc_mbx_read_top_tx_MASK 0x00000003 +#define lpfc_mbx_read_top_tx_WORD word8 +#define lpfc_mbx_read_top_rx_SHIFT 0 +#define lpfc_mbx_read_top_rx_MASK 0x00000003 +#define lpfc_mbx_read_top_rx_WORD word8 +#define LPFC_LINK_SPEED_UNKNOWN 0x0 +#define LPFC_LINK_SPEED_1GHZ 0x04 +#define LPFC_LINK_SPEED_2GHZ 0x08 +#define LPFC_LINK_SPEED_4GHZ 0x10 +#define LPFC_LINK_SPEED_8GHZ 0x20 +#define LPFC_LINK_SPEED_10GHZ 0x40 +#define LPFC_LINK_SPEED_16GHZ 0x80 +}; /* Structure for MB Command CLEAR_LA (22) */ @@ -3018,7 +3012,6 @@ typedef union { READ_LNK_VAR varRdLnk; /* cmd = 18 (READ_LNK_STAT) */ REG_LOGIN_VAR varRegLogin; /* cmd = 19 (REG_LOGIN(64)) */ UNREG_LOGIN_VAR varUnregLogin; /* cmd = 20 (UNREG_LOGIN) */ - READ_LA_VAR varReadLA; /* cmd = 21 (READ_LA(64)) */ CLEAR_LA_VAR varClearLA; /* cmd = 22 (CLEAR_LA) */ DUMP_VAR varDmp; /* Warm Start DUMP mbx cmd */ UNREG_D_ID_VAR varUnregDID; /* cmd = 0x23 (UNREG_D_ID) */ @@ -3028,6 +3021,7 @@ typedef union { struct config_hbq_var varCfgHbq;/* cmd = 0x7c (CONFIG_HBQ) */ struct update_cfg_var varUpdateCfg; /* cmd = 0x1B (UPDATE_CFG)*/ CONFIG_PORT_VAR varCfgPort; /* cmd = 0x88 (CONFIG_PORT) */ + struct lpfc_mbx_read_top varReadTop; /* cmd = 0x95 (READ_TOPOLOGY) */ REG_VPI_VAR varRegVpi; /* cmd = 0x96 (REG_VPI) */ UNREG_VPI_VAR varUnregVpi; /* cmd = 0x97 (UNREG_VPI) */ ASYNCEVT_ENABLE_VAR varCfgAsyncEvent; /*cmd = x33 (CONFIG_ASYNC) */ diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 7fbc58713f19..4e3a11b98299 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -1444,10 +1444,16 @@ struct lpfc_mbx_init_vfi { #define lpfc_init_vfi_vf_SHIFT 29 #define lpfc_init_vfi_vf_MASK 0x00000001 #define lpfc_init_vfi_vf_WORD word1 +#define lpfc_init_vfi_vp_SHIFT 28 +#define lpfc_init_vfi_vp_MASK 0x00000001 +#define lpfc_init_vfi_vp_WORD word1 #define lpfc_init_vfi_vfi_SHIFT 0 #define lpfc_init_vfi_vfi_MASK 0x0000FFFF #define lpfc_init_vfi_vfi_WORD word1 uint32_t word2; +#define lpfc_init_vfi_vpi_SHIFT 16 +#define lpfc_init_vfi_vpi_MASK 0x0000FFFF +#define lpfc_init_vfi_vpi_WORD word2 #define lpfc_init_vfi_fcfi_SHIFT 0 #define lpfc_init_vfi_fcfi_MASK 0x0000FFFF #define lpfc_init_vfi_fcfi_WORD word2 @@ -2155,6 +2161,7 @@ struct lpfc_mcqe { #define LPFC_TRAILER_CODE_FCOE 0x2 #define LPFC_TRAILER_CODE_DCBX 0x3 #define LPFC_TRAILER_CODE_GRP5 0x5 +#define LPFC_TRAILER_CODE_FC 0x10 }; struct lpfc_acqe_link { diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 912b5959f068..432afc7db1cc 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -446,23 +446,25 @@ lpfc_config_port_post(struct lpfc_hba *phba) /* Get the default values for Model Name and Description */ lpfc_get_hba_model_desc(phba, phba->ModelName, phba->ModelDesc); - if ((phba->cfg_link_speed > LINK_SPEED_10G) - || ((phba->cfg_link_speed == LINK_SPEED_1G) + if ((phba->cfg_link_speed > LPFC_USER_LINK_SPEED_16G) + || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_1G) && !(phba->lmt & LMT_1Gb)) - || ((phba->cfg_link_speed == LINK_SPEED_2G) + || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_2G) && !(phba->lmt & LMT_2Gb)) - || ((phba->cfg_link_speed == LINK_SPEED_4G) + || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_4G) && !(phba->lmt & LMT_4Gb)) - || ((phba->cfg_link_speed == LINK_SPEED_8G) + || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_8G) && !(phba->lmt & LMT_8Gb)) - || ((phba->cfg_link_speed == LINK_SPEED_10G) - && !(phba->lmt & LMT_10Gb))) { + || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_10G) + && !(phba->lmt & LMT_10Gb)) + || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_16G) + && !(phba->lmt & LMT_16Gb))) { /* Reset link speed to auto */ lpfc_printf_log(phba, KERN_WARNING, LOG_LINK_EVENT, "1302 Invalid speed for this board: " "Reset link speed to auto: x%x\n", phba->cfg_link_speed); - phba->cfg_link_speed = LINK_SPEED_AUTO; + phba->cfg_link_speed = LPFC_USER_LINK_SPEED_AUTO; } phba->link_state = LPFC_LINK_DOWN; @@ -648,22 +650,23 @@ lpfc_hba_init_link(struct lpfc_hba *phba, uint32_t flag) mb = &pmb->u.mb; pmb->vport = vport; - lpfc_init_link(phba, pmb, phba->cfg_topology, - phba->cfg_link_speed); + lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed); pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; lpfc_set_loopback_flag(phba); rc = lpfc_sli_issue_mbox(phba, pmb, flag); - if (rc != MBX_SUCCESS) { + if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0498 Adapter failed to init, mbxCmd x%x " "INIT_LINK, mbxStatus x%x\n", mb->mbxCommand, mb->mbxStatus); - /* Clear all interrupt enable conditions */ - writel(0, phba->HCregaddr); - readl(phba->HCregaddr); /* flush */ - /* Clear all pending interrupts */ - writel(0xffffffff, phba->HAregaddr); - readl(phba->HAregaddr); /* flush */ + if (phba->sli_rev <= LPFC_SLI_REV3) { + /* Clear all interrupt enable conditions */ + writel(0, phba->HCregaddr); + readl(phba->HCregaddr); /* flush */ + /* Clear all pending interrupts */ + writel(0xffffffff, phba->HAregaddr); + readl(phba->HAregaddr); /* flush */ + } phba->link_state = LPFC_HBA_ERROR; if (rc != MBX_BUSY || flag == MBX_POLL) mempool_free(pmb, phba->mbox_mem_pool); @@ -1459,8 +1462,8 @@ lpfc_handle_latt(struct lpfc_hba *phba) lpfc_els_flush_all_cmd(phba); psli->slistat.link_event++; - lpfc_read_la(phba, pmb, mp); - pmb->mbox_cmpl = lpfc_mbx_cmpl_read_la; + lpfc_read_topology(phba, pmb, mp); + pmb->mbox_cmpl = lpfc_mbx_cmpl_read_topology; pmb->vport = vport; /* Block ELS IOCBs until we have processed this mbox command */ phba->sli.ring[LPFC_ELS_RING].flag |= LPFC_STOP_IOCB_EVENT; @@ -3059,20 +3062,20 @@ lpfc_sli4_parse_latt_type(struct lpfc_hba *phba, switch (bf_get(lpfc_acqe_link_status, acqe_link)) { case LPFC_ASYNC_LINK_STATUS_DOWN: case LPFC_ASYNC_LINK_STATUS_LOGICAL_DOWN: - att_type = AT_LINK_DOWN; + att_type = LPFC_ATT_LINK_DOWN; break; case LPFC_ASYNC_LINK_STATUS_UP: /* Ignore physical link up events - wait for logical link up */ - att_type = AT_RESERVED; + att_type = LPFC_ATT_RESERVED; break; case LPFC_ASYNC_LINK_STATUS_LOGICAL_UP: - att_type = AT_LINK_UP; + att_type = LPFC_ATT_LINK_UP; break; default: lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0399 Invalid link attention type: x%x\n", bf_get(lpfc_acqe_link_status, acqe_link)); - att_type = AT_RESERVED; + att_type = LPFC_ATT_RESERVED; break; } return att_type; @@ -3096,32 +3099,28 @@ lpfc_sli4_parse_latt_link_speed(struct lpfc_hba *phba, switch (bf_get(lpfc_acqe_link_speed, acqe_link)) { case LPFC_ASYNC_LINK_SPEED_ZERO: - link_speed = LA_UNKNW_LINK; - break; case LPFC_ASYNC_LINK_SPEED_10MBPS: - link_speed = LA_UNKNW_LINK; - break; case LPFC_ASYNC_LINK_SPEED_100MBPS: - link_speed = LA_UNKNW_LINK; + link_speed = LPFC_LINK_SPEED_UNKNOWN; break; case LPFC_ASYNC_LINK_SPEED_1GBPS: - link_speed = LA_1GHZ_LINK; + link_speed = LPFC_LINK_SPEED_1GHZ; break; case LPFC_ASYNC_LINK_SPEED_10GBPS: - link_speed = LA_10GHZ_LINK; + link_speed = LPFC_LINK_SPEED_10GHZ; break; default: lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0483 Invalid link-attention link speed: x%x\n", bf_get(lpfc_acqe_link_speed, acqe_link)); - link_speed = LA_UNKNW_LINK; + link_speed = LPFC_LINK_SPEED_UNKNOWN; break; } return link_speed; } /** - * lpfc_sli4_async_link_evt - Process the asynchronous link event + * lpfc_sli4_async_link_evt - Process the asynchronous FC or FCoE link event * @phba: pointer to lpfc hba data structure. * @acqe_link: pointer to the async link completion queue entry. * @@ -3134,11 +3133,12 @@ lpfc_sli4_async_link_evt(struct lpfc_hba *phba, struct lpfc_dmabuf *mp; LPFC_MBOXQ_t *pmb; MAILBOX_t *mb; - READ_LA_VAR *la; + struct lpfc_mbx_read_top *la; uint8_t att_type; + int rc; att_type = lpfc_sli4_parse_latt_type(phba, acqe_link); - if (att_type != AT_LINK_DOWN && att_type != AT_LINK_UP) + if (att_type != LPFC_ATT_LINK_DOWN && att_type != LPFC_ATT_LINK_UP) return; phba->fcoe_eventtag = acqe_link->event_tag; pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); @@ -3169,28 +3169,11 @@ lpfc_sli4_async_link_evt(struct lpfc_hba *phba, /* Update link event statistics */ phba->sli.slistat.link_event++; - /* Create pseudo lpfc_handle_latt mailbox command from link ACQE */ - lpfc_read_la(phba, pmb, mp); + /* Create lpfc_handle_latt mailbox command from link ACQE */ + lpfc_read_topology(phba, pmb, mp); + pmb->mbox_cmpl = lpfc_mbx_cmpl_read_topology; pmb->vport = phba->pport; - /* Parse and translate status field */ - mb = &pmb->u.mb; - mb->mbxStatus = lpfc_sli4_parse_latt_fault(phba, acqe_link); - - /* Parse and translate link attention fields */ - la = (READ_LA_VAR *) &pmb->u.mb.un.varReadLA; - la->eventTag = acqe_link->event_tag; - la->attType = att_type; - la->UlnkSpeed = lpfc_sli4_parse_latt_link_speed(phba, acqe_link); - - /* Fake the the following irrelvant fields */ - la->topology = TOPOLOGY_PT_PT; - la->granted_AL_PA = 0; - la->il = 0; - la->pb = 0; - la->fa = 0; - la->mm = 0; - /* Keep the link status for extra SLI4 state machine reference */ phba->sli4_hba.link_state.speed = bf_get(lpfc_acqe_link_speed, acqe_link); @@ -3204,9 +3187,42 @@ lpfc_sli4_async_link_evt(struct lpfc_hba *phba, bf_get(lpfc_acqe_link_fault, acqe_link); phba->sli4_hba.link_state.logical_speed = bf_get(lpfc_acqe_qos_link_speed, acqe_link); + /* + * For FC Mode: issue the READ_TOPOLOGY mailbox command to fetch + * topology info. Note: Optional for non FC-AL ports. + */ + if (!(phba->hba_flag & HBA_FCOE_MODE)) { + rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); + if (rc == MBX_NOT_FINISHED) + goto out_free_dmabuf; + return; + } + /* + * For FCoE Mode: fill in all the topology information we need and call + * the READ_TOPOLOGY completion routine to continue without actually + * sending the READ_TOPOLOGY mailbox command to the port. + */ + /* Parse and translate status field */ + mb = &pmb->u.mb; + mb->mbxStatus = lpfc_sli4_parse_latt_fault(phba, acqe_link); + + /* Parse and translate link attention fields */ + la = (struct lpfc_mbx_read_top *) &pmb->u.mb.un.varReadTop; + la->eventTag = acqe_link->event_tag; + bf_set(lpfc_mbx_read_top_att_type, la, att_type); + bf_set(lpfc_mbx_read_top_link_spd, la, + lpfc_sli4_parse_latt_link_speed(phba, acqe_link)); + + /* Fake the the following irrelvant fields */ + bf_set(lpfc_mbx_read_top_topology, la, LPFC_TOPOLOGY_PT_PT); + bf_set(lpfc_mbx_read_top_alpa_granted, la, 0); + bf_set(lpfc_mbx_read_top_il, la, 0); + bf_set(lpfc_mbx_read_top_pb, la, 0); + bf_set(lpfc_mbx_read_top_fa, la, 0); + bf_set(lpfc_mbx_read_top_mm, la, 0); /* Invoke the lpfc_handle_latt mailbox command callback function */ - lpfc_mbx_cmpl_read_la(phba, pmb); + lpfc_mbx_cmpl_read_topology(phba, pmb); return; @@ -3295,15 +3311,15 @@ lpfc_sli4_perform_all_vport_cvl(struct lpfc_hba *phba) } /** - * lpfc_sli4_async_fcoe_evt - Process the asynchronous fcoe event + * lpfc_sli4_async_fip_evt - Process the asynchronous FCoE FIP event * @phba: pointer to lpfc hba data structure. * @acqe_link: pointer to the async fcoe completion queue entry. * * This routine is to handle the SLI4 asynchronous fcoe event. **/ static void -lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, - struct lpfc_acqe_fcoe *acqe_fcoe) +lpfc_sli4_async_fip_evt(struct lpfc_hba *phba, + struct lpfc_acqe_fcoe *acqe_fcoe) { uint8_t event_type = bf_get(lpfc_acqe_fcoe_event_type, acqe_fcoe); int rc; @@ -3605,12 +3621,13 @@ void lpfc_sli4_async_event_proc(struct lpfc_hba *phba) /* Process the asynchronous event */ switch (bf_get(lpfc_trailer_code, &cq_event->cqe.mcqe_cmpl)) { case LPFC_TRAILER_CODE_LINK: + case LPFC_TRAILER_CODE_FC: lpfc_sli4_async_link_evt(phba, &cq_event->cqe.acqe_link); break; case LPFC_TRAILER_CODE_FCOE: - lpfc_sli4_async_fcoe_evt(phba, - &cq_event->cqe.acqe_fcoe); + lpfc_sli4_async_fip_evt(phba, + &cq_event->cqe.acqe_fcoe); break; case LPFC_TRAILER_CODE_DCBX: lpfc_sli4_async_dcbx_evt(phba, diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 62d0957e1d4c..b1dab92628ee 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -263,18 +263,19 @@ lpfc_heart_beat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) } /** - * lpfc_read_la - Prepare a mailbox command for reading HBA link attention + * lpfc_read_topology - Prepare a mailbox command for reading HBA topology * @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 + * The read topology mailbox command is issued to read the link topology + * information indicated by the HBA port when the Link Event bit of the Host + * Attention (HSTATT) register is set to 1 (For SLI-3) or when an FC Link + * Attention ACQE is received from the port (For SLI-4). 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 + * This routine prepares the mailbox command for reading HBA link topology * 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. @@ -283,7 +284,8 @@ lpfc_heart_beat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) * 0 - Success (currently always return 0) **/ int -lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, struct lpfc_dmabuf *mp) +lpfc_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, + struct lpfc_dmabuf *mp) { MAILBOX_t *mb; struct lpfc_sli *psli; @@ -293,15 +295,15 @@ lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, struct lpfc_dmabuf *mp) memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); INIT_LIST_HEAD(&mp->list); - mb->mbxCommand = MBX_READ_LA64; - mb->un.varReadLA.un.lilpBde64.tus.f.bdeSize = 128; - mb->un.varReadLA.un.lilpBde64.addrHigh = putPaddrHigh(mp->phys); - mb->un.varReadLA.un.lilpBde64.addrLow = putPaddrLow(mp->phys); + mb->mbxCommand = MBX_READ_TOPOLOGY; + mb->un.varReadTop.lilpBde64.tus.f.bdeSize = LPFC_ALPA_MAP_SIZE; + mb->un.varReadTop.lilpBde64.addrHigh = putPaddrHigh(mp->phys); + mb->un.varReadTop.lilpBde64.addrLow = putPaddrLow(mp->phys); /* Save address for later completion and set the owner to host so that * the FW knows this mailbox is available for processing. */ - pmb->context1 = (uint8_t *) mp; + pmb->context1 = (uint8_t *)mp; mb->mbxOwner = OWN_HOST; return (0); } @@ -516,18 +518,33 @@ lpfc_init_link(struct lpfc_hba * phba, vpd = &phba->vpd; if (vpd->rev.feaLevelHigh >= 0x02){ switch(linkspeed){ - case LINK_SPEED_1G: - case LINK_SPEED_2G: - case LINK_SPEED_4G: - case LINK_SPEED_8G: - mb->un.varInitLnk.link_flags |= - FLAGS_LINK_SPEED; - mb->un.varInitLnk.link_speed = linkspeed; + case LPFC_USER_LINK_SPEED_1G: + mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED; + mb->un.varInitLnk.link_speed = LINK_SPEED_1G; + break; + case LPFC_USER_LINK_SPEED_2G: + mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED; + mb->un.varInitLnk.link_speed = LINK_SPEED_2G; + break; + case LPFC_USER_LINK_SPEED_4G: + mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED; + mb->un.varInitLnk.link_speed = LINK_SPEED_4G; + break; + case LPFC_USER_LINK_SPEED_8G: + mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED; + mb->un.varInitLnk.link_speed = LINK_SPEED_8G; + break; + case LPFC_USER_LINK_SPEED_10G: + mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED; + mb->un.varInitLnk.link_speed = LINK_SPEED_10G; + break; + case LPFC_USER_LINK_SPEED_16G: + mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED; + mb->un.varInitLnk.link_speed = LINK_SPEED_16G; break; - case LINK_SPEED_AUTO: - default: - mb->un.varInitLnk.link_speed = - LINK_SPEED_AUTO; + case LPFC_USER_LINK_SPEED_AUTO: + default: + mb->un.varInitLnk.link_speed = LINK_SPEED_AUTO; break; } @@ -1918,11 +1935,14 @@ lpfc_init_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport) struct lpfc_mbx_init_vfi *init_vfi; memset(mbox, 0, sizeof(*mbox)); + mbox->vport = vport; init_vfi = &mbox->u.mqe.un.init_vfi; bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_INIT_VFI); bf_set(lpfc_init_vfi_vr, init_vfi, 1); bf_set(lpfc_init_vfi_vt, init_vfi, 1); + bf_set(lpfc_init_vfi_vp, init_vfi, 1); bf_set(lpfc_init_vfi_vfi, init_vfi, vport->vfi + vport->phba->vfi_base); + bf_set(lpfc_init_vpi_vpi, init_vfi, vport->vpi + vport->phba->vpi_base); bf_set(lpfc_init_vfi_fcfi, init_vfi, vport->phba->fcf.fcfi); } diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 06b1655b4d59..bedaa4e7cbf8 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -1634,7 +1634,6 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand) case MBX_READ_LNK_STAT: case MBX_REG_LOGIN: case MBX_UNREG_LOGIN: - case MBX_READ_LA: case MBX_CLEAR_LA: case MBX_DUMP_MEMORY: case MBX_DUMP_CONTEXT: @@ -1656,7 +1655,7 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand) case MBX_READ_SPARM64: case MBX_READ_RPI64: case MBX_REG_LOGIN64: - case MBX_READ_LA64: + case MBX_READ_TOPOLOGY: case MBX_WRITE_WWN: case MBX_SET_DEBUG: case MBX_LOAD_EXP_ROM: @@ -4357,13 +4356,16 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) } rc = lpfc_sli4_read_rev(phba, mboxq, vpd, &vpd_size); - if (unlikely(rc)) - goto out_free_vpd; - + if (unlikely(rc)) { + kfree(vpd); + goto out_free_mbox; + } mqe = &mboxq->u.mqe; phba->sli_rev = bf_get(lpfc_mbx_rd_rev_sli_lvl, &mqe->un.read_rev); if (bf_get(lpfc_mbx_rd_rev_fcoe, &mqe->un.read_rev)) - phba->hba_flag |= HBA_FCOE_SUPPORT; + phba->hba_flag |= HBA_FCOE_MODE; + else + phba->hba_flag &= ~HBA_FCOE_MODE; if (bf_get(lpfc_mbx_rd_rev_cee_ver, &mqe->un.read_rev) == LPFC_DCBX_CEE_MODE) @@ -4372,13 +4374,14 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) phba->hba_flag &= ~HBA_FIP_SUPPORT; if (phba->sli_rev != LPFC_SLI_REV4 || - !(phba->hba_flag & HBA_FCOE_SUPPORT)) { + !(phba->hba_flag & HBA_FCOE_MODE)) { lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, "0376 READ_REV Error. SLI Level %d " "FCoE enabled %d\n", - phba->sli_rev, phba->hba_flag & HBA_FCOE_SUPPORT); + phba->sli_rev, phba->hba_flag & HBA_FCOE_MODE); rc = -EIO; - goto out_free_vpd; + kfree(vpd); + goto out_free_mbox; } /* * Evaluate the read rev and vpd data. Populate the driver @@ -4392,6 +4395,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) "Using defaults.\n", rc); rc = 0; } + kfree(vpd); /* Save information as VPD data */ phba->vpd.rev.biuRev = mqe->un.read_rev.first_hw_rev; @@ -4428,7 +4432,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); if (unlikely(rc)) { rc = -EIO; - goto out_free_vpd; + goto out_free_mbox; } /* @@ -4476,7 +4480,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) if (rc) { phba->link_state = LPFC_HBA_ERROR; rc = -ENOMEM; - goto out_free_vpd; + goto out_free_mbox; } mboxq->vport = vport; @@ -4501,7 +4505,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) rc, bf_get(lpfc_mqe_status, mqe)); phba->link_state = LPFC_HBA_ERROR; rc = -EIO; - goto out_free_vpd; + goto out_free_mbox; } if (phba->cfg_soft_wwnn) @@ -4526,7 +4530,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) "0582 Error %d during sgl post operation\n", rc); rc = -ENODEV; - goto out_free_vpd; + goto out_free_mbox; } /* Register SCSI SGL pool to the device */ @@ -4538,7 +4542,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) /* Some Scsi buffers were moved to the abort scsi list */ /* A pci function reset will repost them */ rc = -ENODEV; - goto out_free_vpd; + goto out_free_mbox; } /* Post the rpi header region to the device. */ @@ -4548,7 +4552,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) "0393 Error %d during rpi post operation\n", rc); rc = -ENODEV; - goto out_free_vpd; + goto out_free_mbox; } /* Set up all the queues to the device */ @@ -4608,33 +4612,33 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) } } + if (!(phba->hba_flag & HBA_FCOE_MODE)) { + /* + * The FC Port needs to register FCFI (index 0) + */ + lpfc_reg_fcfi(phba, mboxq); + mboxq->vport = phba->pport; + rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); + if (rc == MBX_SUCCESS) + rc = 0; + else + goto out_unset_queue; + } /* * The port is ready, set the host's link state to LINK_DOWN * in preparation for link interrupts. */ - lpfc_init_link(phba, mboxq, phba->cfg_topology, phba->cfg_link_speed); - mboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl; - lpfc_set_loopback_flag(phba); - /* Change driver state to LPFC_LINK_DOWN right before init link */ spin_lock_irq(&phba->hbalock); phba->link_state = LPFC_LINK_DOWN; spin_unlock_irq(&phba->hbalock); - rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT); - if (unlikely(rc != MBX_NOT_FINISHED)) { - kfree(vpd); - return 0; - } else - rc = -EIO; - + rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT); +out_unset_queue: /* Unset all the queues set up in this routine when error out */ if (rc) lpfc_sli4_queue_unset(phba); - out_stop_timers: if (rc) lpfc_stop_hba_timers(phba); -out_free_vpd: - kfree(vpd); out_free_mbox: mempool_free(mboxq, phba->mbox_mem_pool); return rc; @@ -12157,42 +12161,37 @@ lpfc_sli4_resume_rpi(struct lpfc_nodelist *ndlp) /** * lpfc_sli4_init_vpi - Initialize a vpi with the port - * @phba: pointer to lpfc hba data structure. - * @vpi: vpi value to activate with the port. + * @vport: Pointer to the vport for which the vpi is being initialized * - * This routine is invoked to activate a vpi with the - * port when the host intends to use vports with a - * nonzero vpi. + * This routine is invoked to activate a vpi with the port. * * Returns: * 0 success * -Evalue otherwise **/ int -lpfc_sli4_init_vpi(struct lpfc_hba *phba, uint16_t vpi) +lpfc_sli4_init_vpi(struct lpfc_vport *vport) { LPFC_MBOXQ_t *mboxq; int rc = 0; int retval = MBX_SUCCESS; uint32_t mbox_tmo; - - if (vpi == 0) - return -EINVAL; + struct lpfc_hba *phba = vport->phba; mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mboxq) return -ENOMEM; - lpfc_init_vpi(phba, mboxq, vpi); + lpfc_init_vpi(phba, mboxq, vport->vpi); mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_INIT_VPI); rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo); if (rc != MBX_SUCCESS) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + lpfc_printf_vlog(vport, KERN_ERR, LOG_SLI, "2022 INIT VPI Mailbox failed " "status %d, mbxStatus x%x\n", rc, bf_get(lpfc_mqe_status, &mboxq->u.mqe)); retval = -EIO; } if (rc != MBX_TIMEOUT) - mempool_free(mboxq, phba->mbox_mem_pool); + mempool_free(mboxq, vport->phba->mbox_mem_pool); return retval; } diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index c4483feb8b71..bc30fcf3f804 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -548,7 +548,7 @@ int lpfc_sli4_brdreset(struct lpfc_hba *); int lpfc_sli4_add_fcf_record(struct lpfc_hba *, struct fcf_record *); void lpfc_sli_remove_dflt_fcf(struct lpfc_hba *); int lpfc_sli4_get_els_iocb_cnt(struct lpfc_hba *); -int lpfc_sli4_init_vpi(struct lpfc_hba *, uint16_t); +int lpfc_sli4_init_vpi(struct lpfc_vport *); uint32_t lpfc_sli4_cq_release(struct lpfc_queue *, bool); uint32_t lpfc_sli4_eq_release(struct lpfc_queue *, bool); void lpfc_sli4_fcfi_unreg(struct lpfc_hba *, uint16_t); diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index a5281ce893d0..6b8d2952e32f 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c @@ -395,8 +395,8 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) * by the port. */ if ((phba->sli_rev == LPFC_SLI_REV4) && - (pport->fc_flag & FC_VFI_REGISTERED)) { - rc = lpfc_sli4_init_vpi(phba, vpi); + (pport->fc_flag & FC_VFI_REGISTERED)) { + rc = lpfc_sli4_init_vpi(vport); if (rc) { lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, "1838 Failed to INIT_VPI on vpi %d " @@ -418,7 +418,7 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) if ((phba->link_state < LPFC_LINK_UP) || (pport->port_state < LPFC_FABRIC_CFG_LINK) || - (phba->fc_topology == TOPOLOGY_LOOP)) { + (phba->fc_topology == LPFC_TOPOLOGY_LOOP)) { lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN); rc = VPORT_OK; goto out; @@ -514,7 +514,7 @@ enable_vport(struct fc_vport *fc_vport) struct Scsi_Host *shost = lpfc_shost_from_vport(vport); if ((phba->link_state < LPFC_LINK_UP) || - (phba->fc_topology == TOPOLOGY_LOOP)) { + (phba->fc_topology == LPFC_TOPOLOGY_LOOP)) { lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN); return VPORT_OK; } @@ -665,7 +665,7 @@ lpfc_vport_delete(struct fc_vport *fc_vport) if (ndlp && NLP_CHK_NODE_ACT(ndlp) && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE && phba->link_state >= LPFC_LINK_UP && - phba->fc_topology != TOPOLOGY_LOOP) { + phba->fc_topology != LPFC_TOPOLOGY_LOOP) { if (vport->cfg_enable_da_id) { timeout = msecs_to_jiffies(phba->fc_ratov * 2000); if (!lpfc_ns_cmd(vport, SLI_CTNS_DA_ID, 0, 0)) -- cgit v1.2.3-59-g8ed1b From 19ca760979e4be41a3eb215fb8d0e96637161947 Mon Sep 17 00:00:00 2001 From: James Smart Date: Sat, 20 Nov 2010 23:11:55 -0500 Subject: [SCSI] lpfc 8.3.19: Added support for ELS RRQ command Added support for ELS RRQ command - Add new routine lpfc_set_rrq_active() to track XRI qualifier state. - Add new module parameter lpfc_enable_rrq to control RRQ operation. - Add logic to ELS RRQ completion handler and xri qualifier timeout to clear XRI qualifier state. - Use OX_ID from XRI_ABORTED_CQE for RRQ payload. - Tie abort and XRI_ABORTED_CQE andler to RRQ generation. Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc.h | 7 +- drivers/scsi/lpfc/lpfc_attr.c | 9 + drivers/scsi/lpfc/lpfc_crtn.h | 12 +- drivers/scsi/lpfc/lpfc_disc.h | 17 ++ drivers/scsi/lpfc/lpfc_els.c | 232 ++++++++++++++++++++++- drivers/scsi/lpfc/lpfc_hbadisc.c | 4 + drivers/scsi/lpfc/lpfc_hw.h | 18 ++ drivers/scsi/lpfc/lpfc_init.c | 34 ++++ drivers/scsi/lpfc/lpfc_mem.c | 10 +- drivers/scsi/lpfc/lpfc_scsi.c | 82 +++++++- drivers/scsi/lpfc/lpfc_sli.c | 396 ++++++++++++++++++++++++++++++++++++++- drivers/scsi/lpfc/lpfc_sli.h | 1 + drivers/scsi/lpfc/lpfc_sli4.h | 1 + 13 files changed, 803 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index e86a0d2add3c..746dd3d7a092 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -486,7 +486,7 @@ struct lpfc_hba { int (*lpfc_new_scsi_buf) (struct lpfc_vport *, int); struct lpfc_scsi_buf * (*lpfc_get_scsi_buf) - (struct lpfc_hba *); + (struct lpfc_hba *, struct lpfc_nodelist *); int (*lpfc_scsi_prep_dma_buf) (struct lpfc_hba *, struct lpfc_scsi_buf *); void (*lpfc_scsi_unprep_dma_buf) @@ -574,6 +574,7 @@ struct lpfc_hba { #define HBA_FIP_SUPPORT 0x800 /* FIP support in HBA */ #define HBA_AER_ENABLED 0x1000 /* AER enabled with HBA */ #define HBA_DEVLOSS_TMO 0x2000 /* HBA in devloss timeout */ +#define HBA_RRQ_ACTIVE 0x4000 /* process the rrq active list */ uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/ struct lpfc_dmabuf slim2p; @@ -623,6 +624,7 @@ struct lpfc_hba { /* HBA Config Parameters */ uint32_t cfg_ack0; uint32_t cfg_enable_npiv; + uint32_t cfg_enable_rrq; uint32_t cfg_topology; uint32_t cfg_link_speed; uint32_t cfg_cr_delay; @@ -733,6 +735,7 @@ struct lpfc_hba { uint32_t total_scsi_bufs; struct list_head lpfc_iocb_list; uint32_t total_iocbq_bufs; + struct list_head active_rrq_list; spinlock_t hbalock; /* pci_mem_pools */ @@ -745,6 +748,7 @@ struct lpfc_hba { mempool_t *mbox_mem_pool; mempool_t *nlp_mem_pool; + mempool_t *rrq_pool; struct fc_host_statistics link_stats; enum intr_type_t intr_type; @@ -801,6 +805,7 @@ struct lpfc_hba { unsigned long skipped_hb; struct timer_list hb_tmofunc; uint8_t hb_outstanding; + struct timer_list rrq_tmr; enum hba_temp_state over_temp_state; /* ndlp reference management */ spinlock_t ndlp_lock; diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 45bd72a9f60e..6be942ae8a07 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -1977,6 +1977,13 @@ lpfc_param_show(enable_npiv); lpfc_param_init(enable_npiv, 1, 0, 1); static DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO, lpfc_enable_npiv_show, NULL); +int lpfc_enable_rrq; +module_param(lpfc_enable_rrq, int, 0); +MODULE_PARM_DESC(lpfc_enable_rrq, "Enable RRQ functionality"); +lpfc_param_show(enable_rrq); +lpfc_param_init(enable_rrq, 0, 0, 1); +static DEVICE_ATTR(lpfc_enable_rrq, S_IRUGO, lpfc_enable_rrq_show, NULL); + /* # lpfc_suppress_link_up: Bring link up at initialization # 0x0 = bring link up (issue MBX_INIT_LINK) @@ -3394,6 +3401,7 @@ struct device_attribute *lpfc_hba_attrs[] = { &dev_attr_lpfc_fdmi_on, &dev_attr_lpfc_max_luns, &dev_attr_lpfc_enable_npiv, + &dev_attr_lpfc_enable_rrq, &dev_attr_nport_evt_cnt, &dev_attr_board_mode, &dev_attr_max_vpi, @@ -4610,6 +4618,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) lpfc_link_speed_init(phba, lpfc_link_speed); lpfc_poll_tmo_init(phba, lpfc_poll_tmo); lpfc_enable_npiv_init(phba, lpfc_enable_npiv); + lpfc_enable_rrq_init(phba, lpfc_enable_rrq); lpfc_use_msi_init(phba, lpfc_use_msi); lpfc_fcp_imax_init(phba, lpfc_fcp_imax); lpfc_fcp_wq_count_init(phba, lpfc_fcp_wq_count); diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 1ea3075e3c5d..9b95c50ba704 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -416,5 +416,13 @@ struct lpfc_iocbq *lpfc_sli_ringtx_get(struct lpfc_hba *, int __lpfc_sli_issue_iocb(struct lpfc_hba *, uint32_t, struct lpfc_iocbq *, uint32_t); uint32_t lpfc_drain_txq(struct lpfc_hba *); - - +void lpfc_clr_rrq_active(struct lpfc_hba *, uint16_t, struct lpfc_node_rrq *); +int lpfc_test_rrq_active(struct lpfc_hba *, struct lpfc_nodelist *, uint16_t); +void lpfc_handle_rrq_active(struct lpfc_hba *); +int lpfc_send_rrq(struct lpfc_hba *, struct lpfc_node_rrq *); +int lpfc_set_rrq_active(struct lpfc_hba *, struct lpfc_nodelist *, + uint16_t, uint16_t, uint16_t); +void lpfc_cleanup_wt_rrqs(struct lpfc_hba *); +void lpfc_cleanup_vports_rrqs(struct lpfc_vport *); +struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t, + uint32_t); diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index 7cae69de36f7..2f73252d15f0 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h @@ -68,6 +68,12 @@ struct lpfc_fast_path_event { } un; }; +#define LPFC_SLI4_MAX_XRI 1024 /* Used to make the ndlp's xri_bitmap */ +#define XRI_BITMAP_ULONGS (LPFC_SLI4_MAX_XRI / BITS_PER_LONG) +struct lpfc_node_rrqs { + unsigned long xri_bitmap[XRI_BITMAP_ULONGS]; +}; + struct lpfc_nodelist { struct list_head nlp_listp; struct lpfc_name nlp_portname; @@ -110,8 +116,19 @@ struct lpfc_nodelist { atomic_t cmd_pending; uint32_t cmd_qdepth; unsigned long last_change_time; + struct lpfc_node_rrqs active_rrqs; struct lpfc_scsicmd_bkt *lat_data; /* Latency data */ }; +struct lpfc_node_rrq { + struct list_head list; + uint16_t xritag; + uint16_t send_rrq; + uint16_t rxid; + uint32_t nlp_DID; /* FC D_ID of entry */ + struct lpfc_vport *vport; + struct lpfc_nodelist *ndlp; + unsigned long rrq_stop_time; +}; /* Defines for nlp_flag (uint32) */ #define NLP_IGNR_REG_CMPL 0x00000001 /* Rcvd rscn before we cmpl reg login */ diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 04072ce9c905..0705ad86538f 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1290,6 +1290,7 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, uint32_t rc, keepDID = 0; int put_node; int put_rport; + struct lpfc_node_rrqs rrq; /* Fabric nodes can have the same WWPN so we don't bother searching * by WWPN. Just return the ndlp that was given to us. @@ -1307,6 +1308,7 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, if (new_ndlp == ndlp && NLP_CHK_NODE_ACT(new_ndlp)) return ndlp; + memset(&rrq.xri_bitmap, 0, sizeof(new_ndlp->active_rrqs.xri_bitmap)); if (!new_ndlp) { rc = memcmp(&ndlp->nlp_portname, name, @@ -1327,12 +1329,25 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, if (!new_ndlp) return ndlp; keepDID = new_ndlp->nlp_DID; - } else + if (phba->sli_rev == LPFC_SLI_REV4) + memcpy(&rrq.xri_bitmap, + &new_ndlp->active_rrqs.xri_bitmap, + sizeof(new_ndlp->active_rrqs.xri_bitmap)); + } else { keepDID = new_ndlp->nlp_DID; + if (phba->sli_rev == LPFC_SLI_REV4) + memcpy(&rrq.xri_bitmap, + &new_ndlp->active_rrqs.xri_bitmap, + sizeof(new_ndlp->active_rrqs.xri_bitmap)); + } lpfc_unreg_rpi(vport, new_ndlp); new_ndlp->nlp_DID = ndlp->nlp_DID; new_ndlp->nlp_prev_state = ndlp->nlp_prev_state; + if (phba->sli_rev == LPFC_SLI_REV4) + memcpy(new_ndlp->active_rrqs.xri_bitmap, + &ndlp->active_rrqs.xri_bitmap, + sizeof(ndlp->active_rrqs.xri_bitmap)); if (ndlp->nlp_flag & NLP_NPR_2B_DISC) new_ndlp->nlp_flag |= NLP_NPR_2B_DISC; @@ -1371,12 +1386,20 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, /* Two ndlps cannot have the same did on the nodelist */ ndlp->nlp_DID = keepDID; + if (phba->sli_rev == LPFC_SLI_REV4) + memcpy(&ndlp->active_rrqs.xri_bitmap, + &rrq.xri_bitmap, + sizeof(ndlp->active_rrqs.xri_bitmap)); lpfc_drop_node(vport, ndlp); } else { lpfc_unreg_rpi(vport, ndlp); /* Two ndlps cannot have the same did */ ndlp->nlp_DID = keepDID; + if (phba->sli_rev == LPFC_SLI_REV4) + memcpy(&ndlp->active_rrqs.xri_bitmap, + &rrq.xri_bitmap, + sizeof(ndlp->active_rrqs.xri_bitmap)); lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); /* Since we are swapping the ndlp passed in with the new one * and the did has already been swapped, copy over the @@ -1436,6 +1459,73 @@ lpfc_end_rscn(struct lpfc_vport *vport) } } +/** + * lpfc_cmpl_els_rrq - Completion handled for els RRQs. + * @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 will call the clear rrq function to free the rrq and + * clear the xri's bit in the ndlp's xri_bitmap. If the ndlp does not + * exist then the clear_rrq is still called because the rrq needs to + * be freed. + **/ + +static void +lpfc_cmpl_els_rrq(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, + struct lpfc_iocbq *rspiocb) +{ + struct lpfc_vport *vport = cmdiocb->vport; + IOCB_t *irsp; + struct lpfc_nodelist *ndlp; + struct lpfc_node_rrq *rrq; + + /* we pass cmdiocb to state machine which needs rspiocb as well */ + rrq = cmdiocb->context_un.rrq; + cmdiocb->context_un.rsp_iocb = rspiocb; + + irsp = &rspiocb->iocb; + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, + "RRQ cmpl: status:x%x/x%x did:x%x", + irsp->ulpStatus, irsp->un.ulpWord[4], + irsp->un.elsreq64.remoteID); + + ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID); + if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) || ndlp != rrq->ndlp) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "2882 RRQ completes to NPort x%x " + "with no ndlp. Data: x%x x%x x%x\n", + irsp->un.elsreq64.remoteID, + irsp->ulpStatus, irsp->un.ulpWord[4], + irsp->ulpIoTag); + goto out; + } + + /* rrq completes to NPort */ + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "2880 RRQ completes to NPort x%x " + "Data: x%x x%x x%x x%x x%x\n", + ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4], + irsp->ulpTimeout, rrq->xritag, rrq->rxid); + + if (irsp->ulpStatus) { + /* Check for retry */ + /* RRQ failed Don't print the vport to vport rjts */ + if (irsp->ulpStatus != IOSTAT_LS_RJT || + (((irsp->un.ulpWord[4]) >> 16 != LSRJT_INVALID_CMD) && + ((irsp->un.ulpWord[4]) >> 16 != LSRJT_UNABLE_TPC)) || + (phba)->pport->cfg_log_verbose & LOG_ELS) + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "2881 RRQ failure DID:%06X Status:x%x/x%x\n", + ndlp->nlp_DID, irsp->ulpStatus, + irsp->un.ulpWord[4]); + } +out: + if (rrq) + lpfc_clr_rrq_active(phba, rrq->xritag, rrq); + lpfc_els_free_iocb(phba, cmdiocb); + return; +} /** * lpfc_cmpl_els_plogi - Completion callback function for plogi * @phba: pointer to lpfc hba data structure. @@ -3912,6 +4002,47 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format, return 0; } +/** + * lpfc_els_clear_rrq - Clear the rq that this rrq describes. + * @vport: pointer to a virtual N_Port data structure. + * @iocb: pointer to the lpfc command iocb data structure. + * @ndlp: pointer to a node-list data structure. + * + * Return + **/ +static void +lpfc_els_clear_rrq(struct lpfc_vport *vport, + struct lpfc_iocbq *iocb, struct lpfc_nodelist *ndlp) +{ + struct lpfc_hba *phba = vport->phba; + uint8_t *pcmd; + struct RRQ *rrq; + uint16_t rxid; + struct lpfc_node_rrq *prrq; + + + pcmd = (uint8_t *) (((struct lpfc_dmabuf *) iocb->context2)->virt); + pcmd += sizeof(uint32_t); + rrq = (struct RRQ *)pcmd; + rxid = bf_get(rrq_oxid, rrq); + + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "2883 Clear RRQ for SID:x%x OXID:x%x RXID:x%x" + " x%x x%x\n", + bf_get(rrq_did, rrq), + bf_get(rrq_oxid, rrq), + rxid, + iocb->iotag, iocb->iocb.ulpContext); + + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, + "Clear RRQ: did:x%x flg:x%x exchg:x%.08x", + ndlp->nlp_DID, ndlp->nlp_flag, rrq->rrq_exchg); + prrq = lpfc_get_active_rrq(vport, rxid, ndlp->nlp_DID); + if (prrq) + lpfc_clr_rrq_active(phba, rxid, prrq); + return; +} + /** * lpfc_els_rsp_echo_acc - Issue echo acc response * @vport: pointer to a virtual N_Port data structure. @@ -4801,6 +4932,8 @@ lpfc_els_rcv_rrq(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, struct lpfc_nodelist *ndlp) { lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); + if (vport->phba->sli_rev == LPFC_SLI_REV4) + lpfc_els_clear_rrq(vport, cmdiocb, ndlp); } /** @@ -5203,6 +5336,97 @@ reject_out: return 0; } +/* lpfc_issue_els_rrq - Process an unsolicited rps iocb + * @vport: pointer to a host virtual N_Port data structure. + * @ndlp: pointer to a node-list data structure. + * @did: DID of the target. + * @rrq: Pointer to the rrq struct. + * + * Build a ELS RRQ command and send it to the target. If the issue_iocb is + * Successful the the completion handler will clear the RRQ. + * + * Return codes + * 0 - Successfully sent rrq els iocb. + * 1 - Failed to send rrq els iocb. + **/ +static int +lpfc_issue_els_rrq(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, + uint32_t did, struct lpfc_node_rrq *rrq) +{ + struct lpfc_hba *phba = vport->phba; + struct RRQ *els_rrq; + IOCB_t *icmd; + struct lpfc_iocbq *elsiocb; + uint8_t *pcmd; + uint16_t cmdsize; + int ret; + + + if (ndlp != rrq->ndlp) + ndlp = rrq->ndlp; + if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) + return 1; + + /* If ndlp is not NULL, we will bump the reference count on it */ + cmdsize = (sizeof(uint32_t) + sizeof(struct RRQ)); + elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, 0, ndlp, did, + ELS_CMD_RRQ); + if (!elsiocb) + return 1; + + icmd = &elsiocb->iocb; + pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); + + /* For RRQ request, remainder of payload is Exchange IDs */ + *((uint32_t *) (pcmd)) = ELS_CMD_RRQ; + pcmd += sizeof(uint32_t); + els_rrq = (struct RRQ *) pcmd; + + bf_set(rrq_oxid, els_rrq, rrq->xritag); + bf_set(rrq_rxid, els_rrq, rrq->rxid); + bf_set(rrq_did, els_rrq, vport->fc_myDID); + els_rrq->rrq = cpu_to_be32(els_rrq->rrq); + els_rrq->rrq_exchg = cpu_to_be32(els_rrq->rrq_exchg); + + + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, + "Issue RRQ: did:x%x", + did, rrq->xritag, rrq->rxid); + elsiocb->context_un.rrq = rrq; + elsiocb->iocb_cmpl = lpfc_cmpl_els_rrq; + ret = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); + + if (ret == IOCB_ERROR) { + lpfc_els_free_iocb(phba, elsiocb); + return 1; + } + return 0; +} + +/** + * lpfc_send_rrq - Sends ELS RRQ if needed. + * @phba: pointer to lpfc hba data structure. + * @rrq: pointer to the active rrq. + * + * This routine will call the lpfc_issue_els_rrq if the rrq is + * still active for the xri. If this function returns a failure then + * the caller needs to clean up the RRQ by calling lpfc_clr_active_rrq. + * + * Returns 0 Success. + * 1 Failure. + **/ +int +lpfc_send_rrq(struct lpfc_hba *phba, struct lpfc_node_rrq *rrq) +{ + struct lpfc_nodelist *ndlp = lpfc_findnode_did(rrq->vport, + rrq->nlp_DID); + if (lpfc_test_rrq_active(phba, ndlp, rrq->xritag)) + return lpfc_issue_els_rrq(rrq->vport, ndlp, + rrq->nlp_DID, rrq); + else + return 1; +} + /** * lpfc_els_rsp_rpl_acc - Issue an accept rpl els command * @vport: pointer to a host virtual N_Port data structure. @@ -7373,8 +7597,11 @@ lpfc_sli4_els_xri_aborted(struct lpfc_hba *phba, struct sli4_wcqe_xri_aborted *axri) { uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri); + uint16_t rxid = bf_get(lpfc_wcqe_xa_remote_xid, axri); + struct lpfc_sglq *sglq_entry = NULL, *sglq_next = NULL; unsigned long iflag = 0; + struct lpfc_nodelist *ndlp; struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; spin_lock_irqsave(&phba->hbalock, iflag); @@ -7383,11 +7610,14 @@ lpfc_sli4_els_xri_aborted(struct lpfc_hba *phba, &phba->sli4_hba.lpfc_abts_els_sgl_list, list) { if (sglq_entry->sli4_xritag == xri) { list_del(&sglq_entry->list); + ndlp = sglq_entry->ndlp; + sglq_entry->ndlp = NULL; list_add_tail(&sglq_entry->list, &phba->sli4_hba.lpfc_sgl_list); sglq_entry->state = SGL_FREED; spin_unlock(&phba->sli4_hba.abts_sgl_list_lock); spin_unlock_irqrestore(&phba->hbalock, iflag); + lpfc_set_rrq_active(phba, ndlp, xri, rxid, 1); /* Check if TXQ queue needs to be serviced */ if (pring->txq_cnt) diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index e8d27c958510..91fa65906173 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -607,6 +607,8 @@ lpfc_work_done(struct lpfc_hba *phba) /* Process SLI4 events */ if (phba->pci_dev_grp == LPFC_PCI_DEV_OC) { + if (phba->hba_flag & HBA_RRQ_ACTIVE) + lpfc_handle_rrq_active(phba); if (phba->hba_flag & FCP_XRI_ABORT_EVENT) lpfc_sli4_fcp_xri_abort_event_proc(phba); if (phba->hba_flag & ELS_XRI_ABORT_EVENT) @@ -966,6 +968,7 @@ lpfc_linkup(struct lpfc_hba *phba) struct lpfc_vport **vports; int i; + lpfc_cleanup_wt_rrqs(phba); phba->link_state = LPFC_LINK_UP; /* Unblock fabric iocbs if they are blocked */ @@ -3161,6 +3164,7 @@ lpfc_mbx_cmpl_unreg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) spin_unlock_irq(shost->host_lock); vport->unreg_vpi_cmpl = VPORT_OK; mempool_free(pmb, phba->mbox_mem_pool); + lpfc_cleanup_vports_rrqs(vport); /* * This shost reference might have been taken at the beginning of * lpfc_vport_delete() diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index a253216e1f18..96ed3ba6ba95 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -880,6 +880,24 @@ struct RLS_RSP { /* Structure is in Big Endian format */ uint32_t crcCnt; }; +struct RRQ { /* Structure is in Big Endian format */ + uint32_t rrq; +#define rrq_rsvd_SHIFT 24 +#define rrq_rsvd_MASK 0x000000ff +#define rrq_rsvd_WORD rrq +#define rrq_did_SHIFT 0 +#define rrq_did_MASK 0x00ffffff +#define rrq_did_WORD rrq + uint32_t rrq_exchg; +#define rrq_oxid_SHIFT 16 +#define rrq_oxid_MASK 0xffff +#define rrq_oxid_WORD rrq_exchg +#define rrq_rxid_SHIFT 0 +#define rrq_rxid_MASK 0xffff +#define rrq_rxid_WORD rrq_exchg +}; + + struct RTV_RSP { /* Structure is in Big Endian format */ uint32_t ratov; uint32_t edtov; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 432afc7db1cc..70ba1895b0a1 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -929,6 +929,35 @@ lpfc_hb_timeout(unsigned long ptr) return; } +/** + * lpfc_rrq_timeout - The RRQ-timer timeout handler + * @ptr: unsigned long holds the pointer to lpfc hba data structure. + * + * This is the RRQ-timer timeout handler registered to the lpfc driver. When + * this timer fires, a RRQ 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_rrq_handler. Any periodical operations will + * be performed in the timeout handler and the RRQ timeout event bit shall + * be cleared by the worker thread after it has taken the event bitmap out. + **/ +static void +lpfc_rrq_timeout(unsigned long ptr) +{ + struct lpfc_hba *phba; + uint32_t tmo_posted; + unsigned long iflag; + + phba = (struct lpfc_hba *)ptr; + spin_lock_irqsave(&phba->pport->work_port_lock, iflag); + tmo_posted = phba->hba_flag & HBA_RRQ_ACTIVE; + if (!tmo_posted) + phba->hba_flag |= HBA_RRQ_ACTIVE; + spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag); + if (!tmo_posted) + lpfc_worker_wake_up(phba); +} + /** * lpfc_hb_mbox_cmpl - The lpfc heart-beat mailbox command callback function * @phba: pointer to lpfc hba data structure. @@ -3990,6 +4019,9 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) init_timer(&phba->hb_tmofunc); phba->hb_tmofunc.function = lpfc_hb_timeout; phba->hb_tmofunc.data = (unsigned long)phba; + init_timer(&phba->rrq_tmr); + phba->rrq_tmr.function = lpfc_rrq_timeout; + phba->rrq_tmr.data = (unsigned long)phba; psli = &phba->sli; /* MBOX heartbeat timer */ @@ -8192,6 +8224,8 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) goto out_unset_driver_resource_s4; } + INIT_LIST_HEAD(&phba->active_rrq_list); + /* Set up common device driver resources */ error = lpfc_setup_driver_resource_phase2(phba); if (error) { diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index 8f879e477e9d..cbb48ee8b0bb 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c @@ -113,11 +113,16 @@ lpfc_mem_alloc(struct lpfc_hba *phba, int align) goto fail_free_mbox_pool; if (phba->sli_rev == LPFC_SLI_REV4) { + phba->rrq_pool = + mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE, + sizeof(struct lpfc_node_rrq)); + if (!phba->rrq_pool) + goto fail_free_nlp_mem_pool; phba->lpfc_hrb_pool = pci_pool_create("lpfc_hrb_pool", phba->pcidev, LPFC_HDR_BUF_SIZE, align, 0); if (!phba->lpfc_hrb_pool) - goto fail_free_nlp_mem_pool; + goto fail_free_rrq_mem_pool; phba->lpfc_drb_pool = pci_pool_create("lpfc_drb_pool", phba->pcidev, @@ -147,6 +152,9 @@ lpfc_mem_alloc(struct lpfc_hba *phba, int align) fail_free_hrb_pool: pci_pool_destroy(phba->lpfc_hrb_pool); phba->lpfc_hrb_pool = NULL; + fail_free_rrq_mem_pool: + mempool_destroy(phba->rrq_pool); + phba->rrq_pool = NULL; fail_free_nlp_mem_pool: mempool_destroy(phba->nlp_mem_pool); phba->nlp_mem_pool = NULL; diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 581837b3c71a..c97751c95d77 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -621,10 +621,13 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba, struct sli4_wcqe_xri_aborted *axri) { uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri); + uint16_t rxid = bf_get(lpfc_wcqe_xa_remote_xid, axri); struct lpfc_scsi_buf *psb, *next_psb; unsigned long iflag = 0; struct lpfc_iocbq *iocbq; int i; + struct lpfc_nodelist *ndlp; + int rrq_empty = 0; struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; spin_lock_irqsave(&phba->hbalock, iflag); @@ -637,8 +640,14 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba, psb->status = IOSTAT_SUCCESS; spin_unlock( &phba->sli4_hba.abts_scsi_buf_list_lock); + ndlp = psb->rdata->pnode; + rrq_empty = list_empty(&phba->active_rrq_list); spin_unlock_irqrestore(&phba->hbalock, iflag); + if (ndlp) + lpfc_set_rrq_active(phba, ndlp, xri, rxid, 1); lpfc_release_scsi_buf_s4(phba, psb); + if (rrq_empty) + lpfc_worker_wake_up(phba); return; } } @@ -914,7 +923,7 @@ lpfc_new_scsi_buf(struct lpfc_vport *vport, int num_to_alloc) } /** - * lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list of the HBA + * lpfc_get_scsi_buf_s3 - Get a scsi buffer from lpfc_scsi_buf_list of the HBA * @phba: The HBA for which this call is being executed. * * This routine removes a scsi buffer from head of @phba lpfc_scsi_buf_list list @@ -925,7 +934,7 @@ lpfc_new_scsi_buf(struct lpfc_vport *vport, int num_to_alloc) * Pointer to lpfc_scsi_buf - Success **/ static struct lpfc_scsi_buf* -lpfc_get_scsi_buf(struct lpfc_hba * phba) +lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) { struct lpfc_scsi_buf * lpfc_cmd = NULL; struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list; @@ -941,6 +950,67 @@ lpfc_get_scsi_buf(struct lpfc_hba * phba) spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag); return lpfc_cmd; } +/** + * lpfc_get_scsi_buf_s4 - Get a scsi buffer from lpfc_scsi_buf_list of the HBA + * @phba: The HBA for which this call is being executed. + * + * This routine removes a scsi buffer from head of @phba lpfc_scsi_buf_list list + * and returns to caller. + * + * Return codes: + * NULL - Error + * Pointer to lpfc_scsi_buf - Success + **/ +static struct lpfc_scsi_buf* +lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) +{ + struct lpfc_scsi_buf *lpfc_cmd = NULL; + struct lpfc_scsi_buf *start_lpfc_cmd = NULL; + struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list; + unsigned long iflag = 0; + int found = 0; + + spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag); + list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list); + spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag); + while (!found && lpfc_cmd) { + if (lpfc_test_rrq_active(phba, ndlp, + lpfc_cmd->cur_iocbq.sli4_xritag)) { + lpfc_release_scsi_buf_s4(phba, lpfc_cmd); + spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag); + list_remove_head(scsi_buf_list, lpfc_cmd, + struct lpfc_scsi_buf, list); + spin_unlock_irqrestore(&phba->scsi_buf_list_lock, + iflag); + if (lpfc_cmd == start_lpfc_cmd) { + lpfc_cmd = NULL; + break; + } else + continue; + } + found = 1; + lpfc_cmd->seg_cnt = 0; + lpfc_cmd->nonsg_phys = 0; + lpfc_cmd->prot_seg_cnt = 0; + } + return lpfc_cmd; +} +/** + * lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list of the HBA + * @phba: The HBA for which this call is being executed. + * + * This routine removes a scsi buffer from head of @phba lpfc_scsi_buf_list list + * and returns to caller. + * + * Return codes: + * NULL - Error + * Pointer to lpfc_scsi_buf - Success + **/ +static struct lpfc_scsi_buf* +lpfc_get_scsi_buf(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) +{ + return phba->lpfc_get_scsi_buf(phba, ndlp); +} /** * lpfc_release_scsi_buf - Return a scsi buffer back to hba scsi buf list @@ -2744,18 +2814,19 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) phba->lpfc_scsi_unprep_dma_buf = lpfc_scsi_unprep_dma_buf; phba->lpfc_scsi_prep_cmnd = lpfc_scsi_prep_cmnd; - phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf; switch (dev_grp) { case LPFC_PCI_DEV_LP: phba->lpfc_new_scsi_buf = lpfc_new_scsi_buf_s3; phba->lpfc_scsi_prep_dma_buf = lpfc_scsi_prep_dma_buf_s3; phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s3; + phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s3; break; case LPFC_PCI_DEV_OC: phba->lpfc_new_scsi_buf = lpfc_new_scsi_buf_s4; phba->lpfc_scsi_prep_dma_buf = lpfc_scsi_prep_dma_buf_s4; phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s4; + phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s4; break; default: lpfc_printf_log(phba, KERN_ERR, LOG_INIT, @@ -2764,7 +2835,6 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) return -ENODEV; break; } - phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf; phba->lpfc_rampdown_queue_depth = lpfc_rampdown_queue_depth; phba->lpfc_scsi_cmd_iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl; return 0; @@ -2940,7 +3010,7 @@ lpfc_queuecommand_lck(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth) goto out_host_busy; - lpfc_cmd = lpfc_get_scsi_buf(phba); + lpfc_cmd = lpfc_get_scsi_buf(phba, ndlp); if (lpfc_cmd == NULL) { lpfc_rampdown_queue_depth(phba); @@ -3239,7 +3309,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct lpfc_rport_data *rdata, if (!pnode || !NLP_CHK_NODE_ACT(pnode)) return FAILED; - lpfc_cmd = lpfc_get_scsi_buf(phba); + lpfc_cmd = lpfc_get_scsi_buf(phba, rdata->pnode); if (lpfc_cmd == NULL) return FAILED; lpfc_cmd->timeout = 60; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index bedaa4e7cbf8..752601509549 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -512,9 +512,345 @@ __lpfc_get_active_sglq(struct lpfc_hba *phba, uint16_t xritag) return sglq; } +/** + * __lpfc_set_rrq_active - set RRQ active bit in the ndlp's xri_bitmap. + * @phba: Pointer to HBA context object. + * @ndlp: nodelist pointer for this target. + * @xritag: xri used in this exchange. + * @rxid: Remote Exchange ID. + * @send_rrq: Flag used to determine if we should send rrq els cmd. + * + * This function is called with hbalock held. + * The active bit is set in the ndlp's active rrq xri_bitmap. Allocates an + * rrq struct and adds it to the active_rrq_list. + * + * returns 0 for rrq slot for this xri + * < 0 Were not able to get rrq mem or invalid parameter. + **/ +static int +__lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, + uint16_t xritag, uint16_t rxid, uint16_t send_rrq) +{ + uint16_t adj_xri; + struct lpfc_node_rrq *rrq; + int empty; + + /* + * set the active bit even if there is no mem available. + */ + adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base; + if (!ndlp) + return -EINVAL; + if (test_and_set_bit(adj_xri, ndlp->active_rrqs.xri_bitmap)) + return -EINVAL; + rrq = mempool_alloc(phba->rrq_pool, GFP_KERNEL); + if (rrq) { + rrq->send_rrq = send_rrq; + rrq->xritag = xritag; + rrq->rrq_stop_time = jiffies + HZ * (phba->fc_ratov + 1); + rrq->ndlp = ndlp; + rrq->nlp_DID = ndlp->nlp_DID; + rrq->vport = ndlp->vport; + rrq->rxid = rxid; + empty = list_empty(&phba->active_rrq_list); + if (phba->cfg_enable_rrq && send_rrq) + /* + * We need the xri before we can add this to the + * phba active rrq list. + */ + rrq->send_rrq = send_rrq; + else + rrq->send_rrq = 0; + list_add_tail(&rrq->list, &phba->active_rrq_list); + if (!(phba->hba_flag & HBA_RRQ_ACTIVE)) { + phba->hba_flag |= HBA_RRQ_ACTIVE; + if (empty) + lpfc_worker_wake_up(phba); + } + return 0; + } + return -ENOMEM; +} + +/** + * __lpfc_clr_rrq_active - Clears RRQ active bit in xri_bitmap. + * @phba: Pointer to HBA context object. + * @xritag: xri used in this exchange. + * @rrq: The RRQ to be cleared. + * + * This function is called with hbalock held. This function + **/ +static void +__lpfc_clr_rrq_active(struct lpfc_hba *phba, + uint16_t xritag, + struct lpfc_node_rrq *rrq) +{ + uint16_t adj_xri; + struct lpfc_nodelist *ndlp; + + ndlp = lpfc_findnode_did(rrq->vport, rrq->nlp_DID); + + /* The target DID could have been swapped (cable swap) + * we should use the ndlp from the findnode if it is + * available. + */ + if (!ndlp) + ndlp = rrq->ndlp; + + adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base; + if (test_and_clear_bit(adj_xri, ndlp->active_rrqs.xri_bitmap)) { + rrq->send_rrq = 0; + rrq->xritag = 0; + rrq->rrq_stop_time = 0; + } + mempool_free(rrq, phba->rrq_pool); +} + +/** + * lpfc_handle_rrq_active - Checks if RRQ has waithed RATOV. + * @phba: Pointer to HBA context object. + * + * This function is called with hbalock held. This function + * Checks if stop_time (ratov from setting rrq active) has + * been reached, if it has and the send_rrq flag is set then + * it will call lpfc_send_rrq. If the send_rrq flag is not set + * then it will just call the routine to clear the rrq and + * free the rrq resource. + * The timer is set to the next rrq that is going to expire before + * leaving the routine. + * + **/ +void +lpfc_handle_rrq_active(struct lpfc_hba *phba) +{ + struct lpfc_node_rrq *rrq; + struct lpfc_node_rrq *nextrrq; + unsigned long next_time; + unsigned long iflags; + + spin_lock_irqsave(&phba->hbalock, iflags); + phba->hba_flag &= ~HBA_RRQ_ACTIVE; + next_time = jiffies + HZ * (phba->fc_ratov + 1); + list_for_each_entry_safe(rrq, nextrrq, + &phba->active_rrq_list, list) { + if (time_after(jiffies, rrq->rrq_stop_time)) { + list_del(&rrq->list); + if (!rrq->send_rrq) + /* this call will free the rrq */ + __lpfc_clr_rrq_active(phba, rrq->xritag, rrq); + else { + /* if we send the rrq then the completion handler + * will clear the bit in the xribitmap. + */ + spin_unlock_irqrestore(&phba->hbalock, iflags); + if (lpfc_send_rrq(phba, rrq)) { + lpfc_clr_rrq_active(phba, rrq->xritag, + rrq); + } + spin_lock_irqsave(&phba->hbalock, iflags); + } + } else if (time_before(rrq->rrq_stop_time, next_time)) + next_time = rrq->rrq_stop_time; + } + spin_unlock_irqrestore(&phba->hbalock, iflags); + if (!list_empty(&phba->active_rrq_list)) + mod_timer(&phba->rrq_tmr, next_time); +} + +/** + * lpfc_get_active_rrq - Get the active RRQ for this exchange. + * @vport: Pointer to vport context object. + * @xri: The xri used in the exchange. + * @did: The targets DID for this exchange. + * + * returns NULL = rrq not found in the phba->active_rrq_list. + * rrq = rrq for this xri and target. + **/ +struct lpfc_node_rrq * +lpfc_get_active_rrq(struct lpfc_vport *vport, uint16_t xri, uint32_t did) +{ + struct lpfc_hba *phba = vport->phba; + struct lpfc_node_rrq *rrq; + struct lpfc_node_rrq *nextrrq; + unsigned long iflags; + + if (phba->sli_rev != LPFC_SLI_REV4) + return NULL; + spin_lock_irqsave(&phba->hbalock, iflags); + list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list) { + if (rrq->vport == vport && rrq->xritag == xri && + rrq->nlp_DID == did){ + list_del(&rrq->list); + spin_unlock_irqrestore(&phba->hbalock, iflags); + return rrq; + } + } + spin_unlock_irqrestore(&phba->hbalock, iflags); + return NULL; +} + +/** + * lpfc_cleanup_vports_rrqs - Remove and clear the active RRQ for this vport. + * @vport: Pointer to vport context object. + * + * Remove all active RRQs for this vport from the phba->active_rrq_list and + * clear the rrq. + **/ +void +lpfc_cleanup_vports_rrqs(struct lpfc_vport *vport) + +{ + struct lpfc_hba *phba = vport->phba; + struct lpfc_node_rrq *rrq; + struct lpfc_node_rrq *nextrrq; + unsigned long iflags; + + if (phba->sli_rev != LPFC_SLI_REV4) + return; + spin_lock_irqsave(&phba->hbalock, iflags); + list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list) { + if (rrq->vport == vport) { + list_del(&rrq->list); + __lpfc_clr_rrq_active(phba, rrq->xritag, rrq); + } + } + spin_unlock_irqrestore(&phba->hbalock, iflags); +} + +/** + * lpfc_cleanup_wt_rrqs - Remove all rrq's from the active list. + * @phba: Pointer to HBA context object. + * + * Remove all rrqs from the phba->active_rrq_list and free them by + * calling __lpfc_clr_active_rrq + * + **/ +void +lpfc_cleanup_wt_rrqs(struct lpfc_hba *phba) +{ + struct lpfc_node_rrq *rrq; + struct lpfc_node_rrq *nextrrq; + unsigned long next_time; + unsigned long iflags; + + if (phba->sli_rev != LPFC_SLI_REV4) + return; + spin_lock_irqsave(&phba->hbalock, iflags); + phba->hba_flag &= ~HBA_RRQ_ACTIVE; + next_time = jiffies + HZ * (phba->fc_ratov * 2); + list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list) { + list_del(&rrq->list); + __lpfc_clr_rrq_active(phba, rrq->xritag, rrq); + } + spin_unlock_irqrestore(&phba->hbalock, iflags); + if (!list_empty(&phba->active_rrq_list)) + mod_timer(&phba->rrq_tmr, next_time); +} + + +/** + * __lpfc_test_rrq_active - Test RRQ bit in xri_bitmap. + * @phba: Pointer to HBA context object. + * @ndlp: Targets nodelist pointer for this exchange. + * @xritag the xri in the bitmap to test. + * + * This function is called with hbalock held. This function + * returns 0 = rrq not active for this xri + * 1 = rrq is valid for this xri. + **/ +static int +__lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, + uint16_t xritag) +{ + uint16_t adj_xri; + + adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base; + if (!ndlp) + return 0; + if (test_bit(adj_xri, ndlp->active_rrqs.xri_bitmap)) + return 1; + else + return 0; +} + +/** + * lpfc_set_rrq_active - set RRQ active bit in xri_bitmap. + * @phba: Pointer to HBA context object. + * @ndlp: nodelist pointer for this target. + * @xritag: xri used in this exchange. + * @rxid: Remote Exchange ID. + * @send_rrq: Flag used to determine if we should send rrq els cmd. + * + * This function takes the hbalock. + * The active bit is always set in the active rrq xri_bitmap even + * if there is no slot avaiable for the other rrq information. + * + * returns 0 rrq actived for this xri + * < 0 No memory or invalid ndlp. + **/ +int +lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, + uint16_t xritag, uint16_t rxid, uint16_t send_rrq) +{ + int ret; + unsigned long iflags; + + spin_lock_irqsave(&phba->hbalock, iflags); + ret = __lpfc_set_rrq_active(phba, ndlp, xritag, rxid, send_rrq); + spin_unlock_irqrestore(&phba->hbalock, iflags); + return ret; +} + +/** + * lpfc_clr_rrq_active - Clears RRQ active bit in xri_bitmap. + * @phba: Pointer to HBA context object. + * @xritag: xri used in this exchange. + * @rrq: The RRQ to be cleared. + * + * This function is takes the hbalock. + **/ +void +lpfc_clr_rrq_active(struct lpfc_hba *phba, + uint16_t xritag, + struct lpfc_node_rrq *rrq) +{ + unsigned long iflags; + + spin_lock_irqsave(&phba->hbalock, iflags); + __lpfc_clr_rrq_active(phba, xritag, rrq); + spin_unlock_irqrestore(&phba->hbalock, iflags); + return; +} + + + +/** + * lpfc_test_rrq_active - Test RRQ bit in xri_bitmap. + * @phba: Pointer to HBA context object. + * @ndlp: Targets nodelist pointer for this exchange. + * @xritag the xri in the bitmap to test. + * + * This function takes the hbalock. + * returns 0 = rrq not active for this xri + * 1 = rrq is valid for this xri. + **/ +int +lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, + uint16_t xritag) +{ + int ret; + unsigned long iflags; + + spin_lock_irqsave(&phba->hbalock, iflags); + ret = __lpfc_test_rrq_active(phba, ndlp, xritag); + spin_unlock_irqrestore(&phba->hbalock, iflags); + return ret; +} + /** * __lpfc_sli_get_sglq - Allocates an iocb object from sgl pool * @phba: Pointer to HBA context object. + * @piocb: Pointer to the iocbq. * * This function is called with hbalock held. This function * Gets a new driver sglq object from the sglq list. If the @@ -522,17 +858,53 @@ __lpfc_get_active_sglq(struct lpfc_hba *phba, uint16_t xritag) * allocated sglq object else it returns NULL. **/ static struct lpfc_sglq * -__lpfc_sli_get_sglq(struct lpfc_hba *phba) +__lpfc_sli_get_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq) { struct list_head *lpfc_sgl_list = &phba->sli4_hba.lpfc_sgl_list; struct lpfc_sglq *sglq = NULL; + struct lpfc_sglq *start_sglq = NULL; uint16_t adj_xri; + struct lpfc_scsi_buf *lpfc_cmd; + struct lpfc_nodelist *ndlp; + int found = 0; + + if (piocbq->iocb_flag & LPFC_IO_FCP) { + lpfc_cmd = (struct lpfc_scsi_buf *) piocbq->context1; + ndlp = lpfc_cmd->rdata->pnode; + } else if (piocbq->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) + ndlp = piocbq->context_un.ndlp; + else if (piocbq->iocb.ulpCommand == CMD_XMIT_BLS_RSP64_CX) + ndlp = lpfc_findnode_did(piocbq->vport, + piocbq->iocb.ulpContext); + else + ndlp = piocbq->context1; + list_remove_head(lpfc_sgl_list, sglq, struct lpfc_sglq, list); - if (!sglq) - return NULL; - adj_xri = sglq->sli4_xritag - phba->sli4_hba.max_cfg_param.xri_base; - phba->sli4_hba.lpfc_sglq_active_list[adj_xri] = sglq; - sglq->state = SGL_ALLOCATED; + start_sglq = sglq; + while (!found) { + if (!sglq) + return NULL; + adj_xri = sglq->sli4_xritag - + phba->sli4_hba.max_cfg_param.xri_base; + if (__lpfc_test_rrq_active(phba, ndlp, sglq->sli4_xritag)) { + /* This xri has an rrq outstanding for this DID. + * put it back in the list and get another xri. + */ + list_add_tail(&sglq->list, lpfc_sgl_list); + sglq = NULL; + list_remove_head(lpfc_sgl_list, sglq, + struct lpfc_sglq, list); + if (sglq == start_sglq) { + sglq = NULL; + break; + } else + continue; + } + sglq->ndlp = ndlp; + found = 1; + phba->sli4_hba.lpfc_sglq_active_list[adj_xri] = sglq; + sglq->state = SGL_ALLOCATED; + } return sglq; } @@ -598,6 +970,7 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) &phba->sli4_hba.abts_sgl_list_lock, iflag); } else { sglq->state = SGL_FREED; + sglq->ndlp = NULL; list_add(&sglq->list, &phba->sli4_hba.lpfc_sgl_list); /* Check if TXQ queue needs to be serviced */ @@ -6352,7 +6725,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, return IOCB_BUSY; } } else { - sglq = __lpfc_sli_get_sglq(phba); + sglq = __lpfc_sli_get_sglq(phba, piocb); if (!sglq) { if (!(flag & SLI_IOCB_RET_IOCB)) { __lpfc_sli_ringtx_put(phba, @@ -11570,6 +11943,10 @@ lpfc_sli4_seq_abort_acc(struct lpfc_hba *phba, "SID:x%x\n", oxid, sid); return; } + if (rxid >= phba->sli4_hba.max_cfg_param.xri_base + && rxid <= (phba->sli4_hba.max_cfg_param.max_xri + + phba->sli4_hba.max_cfg_param.xri_base)) + lpfc_set_rrq_active(phba, ndlp, rxid, oxid, 0); /* Allocate buffer for acc iocb */ ctiocb = lpfc_sli_get_iocbq(phba); @@ -13008,12 +13385,13 @@ lpfc_drain_txq(struct lpfc_hba *phba) while (pring->txq_cnt) { spin_lock_irqsave(&phba->hbalock, iflags); - sglq = __lpfc_sli_get_sglq(phba); + piocbq = lpfc_sli_ringtx_get(phba, pring); + sglq = __lpfc_sli_get_sglq(phba, piocbq); if (!sglq) { + __lpfc_sli_ringtx_put(phba, pring, piocbq); spin_unlock_irqrestore(&phba->hbalock, iflags); break; } else { - piocbq = lpfc_sli_ringtx_get(phba, pring); if (!piocbq) { /* The txq_cnt out of sync. This should * never happen diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index cd56d6cce6c3..402a0737076c 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h @@ -82,6 +82,7 @@ struct lpfc_iocbq { struct lpfc_iocbq *rsp_iocb; struct lpfcMboxq *mbox; struct lpfc_nodelist *ndlp; + struct lpfc_node_rrq *rrq; } context_un; void (*fabric_iocb_cmpl) (struct lpfc_hba *, struct lpfc_iocbq *, diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index bc30fcf3f804..8ced5983d3e3 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -466,6 +466,7 @@ struct lpfc_sglq { struct list_head clist; enum lpfc_sge_type buff_type; /* is this a scsi sgl */ enum lpfc_sgl_state state; + struct lpfc_nodelist *ndlp; /* ndlp associated with IO */ uint16_t iotag; /* pre-assigned IO tag */ uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */ struct sli4_sge *sgl; /* pre-assigned SGL */ -- cgit v1.2.3-59-g8ed1b From eb7a339e67dceec30f70a5cbed8e2bf6d8318f20 Mon Sep 17 00:00:00 2001 From: James Smart Date: Sat, 20 Nov 2010 23:12:02 -0500 Subject: [SCSI] lpfc 8.3.19: Change heartbeat to default to disabled Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_attr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 6be942ae8a07..c06491b5862f 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -3305,12 +3305,12 @@ LPFC_ATTR_R(fcp_eq_count, LPFC_FP_EQN_DEF, LPFC_FP_EQN_MIN, LPFC_FP_EQN_MAX, LPFC_ATTR_R(enable_hba_reset, 1, 0, 1, "Enable HBA resets from the driver."); /* -# lpfc_enable_hba_heartbeat: Enable HBA heartbeat timer.. +# lpfc_enable_hba_heartbeat: Disable HBA heartbeat timer.. # 0 = HBA Heartbeat disabled # 1 = HBA Heartbeat enabled (default) # Value range is [0,1]. Default value is 1. */ -LPFC_ATTR_R(enable_hba_heartbeat, 1, 0, 1, "Enable HBA Heartbeat."); +LPFC_ATTR_R(enable_hba_heartbeat, 0, 0, 1, "Enable HBA Heartbeat."); /* # lpfc_enable_bg: Enable BlockGuard (Emulex's Implementation of T10-DIF) -- cgit v1.2.3-59-g8ed1b From 1f768e91e1fcd9f0df657783847347a833fdc573 Mon Sep 17 00:00:00 2001 From: James Smart Date: Sat, 20 Nov 2010 23:12:11 -0500 Subject: [SCSI] lpfc 8.3.19: Update lpfc driver version to 8.3.19 Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 7a1b5b112a0b..10511c58f4d9 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -18,7 +18,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "8.3.18" +#define LPFC_DRIVER_VERSION "8.3.19" #define LPFC_DRIVER_NAME "lpfc" #define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp" #define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp" -- cgit v1.2.3-59-g8ed1b From 363fa50fc35357b1361fb63b0726335de993374a Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Sat, 13 Nov 2010 04:29:20 +0530 Subject: [SCSI] mpt2sas: Removed compiler warnnings when logging is disabled The compiler throws warning messages while compiling without CONFIG_SCSI_MPT2SAS_LOGGING. Set proper ifdef for CONFIG_SCSI_MPT2SAS_LOGGING to avoid warnnings. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_ctl.c | 2 +- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c index 40cb8aeb21b1..e92b77af5484 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c @@ -81,6 +81,7 @@ enum block_state { BLOCKING, }; +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING /** * _ctl_sas_device_find_by_handle - sas device search * @ioc: per adapter object @@ -107,7 +108,6 @@ _ctl_sas_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) return r; } -#ifdef CONFIG_SCSI_MPT2SAS_LOGGING /** * _ctl_display_some_debug - debug routine * @ioc: per adapter object diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 1a96a00418a4..5af5781d9464 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -2715,9 +2715,10 @@ static u8 _scsih_sas_control_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) { +#ifdef CONFIG_SCSI_MPT2SAS_LOGGING Mpi2SasIoUnitControlReply_t *mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); - +#endif dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "sc_complete:handle(0x%04x), (open) " "smid(%d), ioc_status(0x%04x), loginfo(0x%08x)\n", -- cgit v1.2.3-59-g8ed1b From dd3741d30300f9cf1adc046773a4bb87252d96ac Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Sat, 13 Nov 2010 04:31:14 +0530 Subject: [SCSI] mpt2sas: Added sanity check for cb_idx and smid access. Sometime it is seen that controller firmware returns an invalid system message id (smid). the oops is occurring becuase mpt_callbacks pointer is referenced to either null or invalid virtual address. this is due to cb_idx set incorrectly from routine _base_get_cb_idx. the cb_idx was set incorrectly becuase there is no check to make sure smid is less than maxiumum anticapted smid. to fix this issue, we add a check in _base_get_cb_idx to make sure smid is not greater than ioc->hba_queue_depth. in addition, a similar check was added to make sure the reply address was less than the largest anticapated address. Newer firmware has sovled this issue, however it good to have this sanity check. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 8 +++++++- drivers/scsi/mpt2sas/mpt2sas_base.h | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 12faf64f91b0..d1c53455c063 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -758,7 +758,7 @@ _base_get_cb_idx(struct MPT2SAS_ADAPTER *ioc, u16 smid) if (smid < ioc->internal_smid) { i = smid - ioc->hi_priority_smid; cb_idx = ioc->hpr_lookup[i].cb_idx; - } else { + } else if (smid <= ioc->hba_queue_depth) { i = smid - ioc->internal_smid; cb_idx = ioc->internal_lookup[i].cb_idx; } @@ -848,6 +848,7 @@ _base_interrupt(int irq, void *bus_id) return IRQ_NONE; completed_cmds = 0; + cb_idx = 0xFF; do { rd.word = rpf->Words; if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX) @@ -860,6 +861,9 @@ _base_interrupt(int irq, void *bus_id) MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) { reply = le32_to_cpu (rpf->AddressReply.ReplyFrameAddress); + if (reply > ioc->reply_dma_max_address || + reply < ioc->reply_dma_min_address) + reply = 0; } else if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER) goto next; @@ -2221,6 +2225,8 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) ioc->name); goto out; } + ioc->reply_dma_min_address = (u32)(ioc->reply_dma); + ioc->reply_dma_max_address = (u32)(ioc->reply_dma) + sz; dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply pool(0x%p): depth" "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->reply, ioc->reply_free_queue_depth, ioc->reply_sz, sz/1024)); diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index 0b15a8bdebfc..63f7a196f42d 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -737,6 +737,8 @@ struct MPT2SAS_ADAPTER { u16 reply_sz; u8 *reply; dma_addr_t reply_dma; + u32 reply_dma_max_address; + u32 reply_dma_min_address; struct dma_pool *reply_dma_pool; /* reply free queue */ -- cgit v1.2.3-59-g8ed1b From 6cb8ef573fd4c2bd72248f492fe336133660148d Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Sat, 13 Nov 2010 04:32:18 +0530 Subject: [SCSI] mpt2sas: Added loadtime para for IOMissingDelay and DMD Ability to override/set the ReportDeviceMissingDelay and IODeviceMissingDelay from driver: Add new command line option missing_delay, this is an array, where the first element is the device missing delay, and the second element is io missing delay. The driver will program sas iounit page 1 with the new setting when the driver loads. This is programmed to the current and persistent configuration page so this takes immediately, as will be sticky across host reboots. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 100 ++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index d1c53455c063..0e30827d44e7 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -79,6 +79,10 @@ static int msix_disable = -1; module_param(msix_disable, int, 0); MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)"); +static int missing_delay[2] = {-1, -1}; +module_param_array(missing_delay, int, NULL, 0); +MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay"); + /* diag_buffer_enable is bitwise * bit 0 set = TRACE * bit 1 set = SNAPSHOT @@ -1822,6 +1826,97 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc) printk(")\n"); } +/** + * _base_update_missing_delay - change the missing delay timers + * @ioc: per adapter object + * @device_missing_delay: amount of time till device is reported missing + * @io_missing_delay: interval IO is returned when there is a missing device + * + * Return nothing. + * + * Passed on the command line, this function will modify the device missing + * delay, as well as the io missing delay. This should be called at driver + * load time. + */ +static void +_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc, + u16 device_missing_delay, u8 io_missing_delay) +{ + u16 dmd, dmd_new, dmd_orignal; + u8 io_missing_delay_original; + u16 sz; + Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL; + Mpi2ConfigReply_t mpi_reply; + u8 num_phys = 0; + u16 ioc_status; + + mpt2sas_config_get_number_hba_phys(ioc, &num_phys); + if (!num_phys) + return; + + sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (num_phys * + sizeof(Mpi2SasIOUnit1PhyData_t)); + sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL); + if (!sas_iounit_pg1) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + goto out; + } + if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply, + sas_iounit_pg1, sz))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + goto out; + } + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + goto out; + } + + /* device missing delay */ + dmd = sas_iounit_pg1->ReportDeviceMissingDelay; + if (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16) + dmd = (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16; + else + dmd = dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK; + dmd_orignal = dmd; + if (device_missing_delay > 0x7F) { + dmd = (device_missing_delay > 0x7F0) ? 0x7F0 : + device_missing_delay; + dmd = dmd / 16; + dmd |= MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16; + } else + dmd = device_missing_delay; + sas_iounit_pg1->ReportDeviceMissingDelay = dmd; + + /* io missing delay */ + io_missing_delay_original = sas_iounit_pg1->IODeviceMissingDelay; + sas_iounit_pg1->IODeviceMissingDelay = io_missing_delay; + + if (!mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, + sz)) { + if (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16) + dmd_new = (dmd & + MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16; + else + dmd_new = + dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK; + printk(MPT2SAS_INFO_FMT "device_missing_delay: old(%d), " + "new(%d)\n", ioc->name, dmd_orignal, dmd_new); + printk(MPT2SAS_INFO_FMT "ioc_missing_delay: old(%d), " + "new(%d)\n", ioc->name, io_missing_delay_original, + io_missing_delay); + ioc->device_missing_delay = dmd_new; + ioc->io_missing_delay = io_missing_delay; + } + +out: + kfree(sas_iounit_pg1); +} + /** * _base_static_config_pages - static start of day config pages * @ioc: per adapter object @@ -1859,6 +1954,7 @@ _base_static_config_pages(struct MPT2SAS_ADAPTER *ioc) MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING; ioc->iounit_pg1.Flags = cpu_to_le32(iounit_pg1_flags); mpt2sas_config_set_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1); + } /** @@ -3720,6 +3816,10 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) if (r) goto out_free_resources; + if (missing_delay[0] != -1 && missing_delay[1] != -1) + _base_update_missing_delay(ioc, missing_delay[0], + missing_delay[1]); + mpt2sas_base_start_watchdog(ioc); return 0; -- cgit v1.2.3-59-g8ed1b From 35f805b52c94f8e6cb22907ef32517132a15cb96 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Sat, 13 Nov 2010 04:34:06 +0530 Subject: [SCSI] mpt2sas: Create a pool of chain buffer instead of dedicated per IOs Create a pool of chain buffers, instead of dedicated per IO: This enahancment is to address memory allocation failure when asking for more than 2300 IOs per host. There is just not enough contiquious DMA physical memory to make one single allocation to hold both message frames and chain buffers when asking for more than 2300 request. In order to address this problem we will have to allocate memory for each chain buffer in a seperate individual memory allocation, placing each chain element of 128 bytes onto a pool of available chains, which can be shared amoung all request. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 87 +++++++++++++++++++++++++++++------- drivers/scsi/mpt2sas/mpt2sas_base.h | 19 +++++++- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 56 +++++++++++++---------- 3 files changed, 119 insertions(+), 43 deletions(-) diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 0e30827d44e7..c8f39f8c6fed 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -65,7 +65,6 @@ static MPT_CALLBACK mpt_callbacks[MPT_MAX_CALLBACKS]; #define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */ -#define MPT2SAS_MAX_REQUEST_QUEUE 600 /* maximum controller queue depth */ static int max_queue_depth = -1; module_param(max_queue_depth, int, 0); @@ -1497,6 +1496,7 @@ mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid) { unsigned long flags; int i; + struct chain_tracker *chain_req, *next; spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); if (smid >= ioc->hi_priority_smid) { @@ -1519,6 +1519,14 @@ mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid) /* scsiio queue */ i = smid - 1; + if (!list_empty(&ioc->scsi_lookup[i].chain_list)) { + list_for_each_entry_safe(chain_req, next, + &ioc->scsi_lookup[i].chain_list, tracker_list) { + list_del_init(&chain_req->tracker_list); + list_add_tail(&chain_req->tracker_list, + &ioc->free_chain_list); + } + } ioc->scsi_lookup[i].cb_idx = 0xFF; ioc->scsi_lookup[i].scmd = NULL; list_add_tail(&ioc->scsi_lookup[i].tracker_list, @@ -1968,6 +1976,8 @@ _base_static_config_pages(struct MPT2SAS_ADAPTER *ioc) static void _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc) { + int i; + dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); @@ -2032,6 +2042,20 @@ _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc) } kfree(ioc->hpr_lookup); kfree(ioc->internal_lookup); + if (ioc->chain_lookup) { + for (i = 0; i < ioc->chain_depth; i++) { + if (ioc->chain_lookup[i].chain_buffer) + pci_pool_free(ioc->chain_dma_pool, + ioc->chain_lookup[i].chain_buffer, + ioc->chain_lookup[i].chain_buffer_dma); + } + if (ioc->chain_dma_pool) + pci_pool_destroy(ioc->chain_dma_pool); + } + if (ioc->chain_lookup) { + free_pages((ulong)ioc->chain_lookup, ioc->chain_pages); + ioc->chain_lookup = NULL; + } } @@ -2053,6 +2077,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) u32 sz, total_sz; u32 retry_sz; u16 max_request_credit; + int i; dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__)); @@ -2070,14 +2095,11 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) } /* command line tunables for max controller queue depth */ - if (max_queue_depth != -1) { + if (max_queue_depth != -1) max_request_credit = (max_queue_depth < facts->RequestCredit) ? max_queue_depth : facts->RequestCredit; - } else { - max_request_credit = (facts->RequestCredit > - MPT2SAS_MAX_REQUEST_QUEUE) ? MPT2SAS_MAX_REQUEST_QUEUE : - facts->RequestCredit; - } + else + max_request_credit = facts->RequestCredit; ioc->hba_queue_depth = max_request_credit; ioc->hi_priority_depth = facts->HighPriorityCredit; @@ -2183,7 +2205,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) * "frame for smid=0 */ ioc->chain_depth = ioc->chains_needed_per_io * ioc->scsiio_depth; - sz = ((ioc->scsiio_depth + 1 + ioc->chain_depth) * ioc->request_sz); + sz = ((ioc->scsiio_depth + 1) * ioc->request_sz); /* hi-priority queue */ sz += (ioc->hi_priority_depth * ioc->request_sz); @@ -2224,19 +2246,11 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) ioc->internal_dma = ioc->hi_priority_dma + (ioc->hi_priority_depth * ioc->request_sz); - ioc->chain = ioc->internal + (ioc->internal_depth * - ioc->request_sz); - ioc->chain_dma = ioc->internal_dma + (ioc->internal_depth * - ioc->request_sz); dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool(0x%p): " "depth(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->request, ioc->hba_queue_depth, ioc->request_sz, (ioc->hba_queue_depth * ioc->request_sz)/1024)); - dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "chain pool(0x%p): depth" - "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->chain, - ioc->chain_depth, ioc->request_sz, ((ioc->chain_depth * - ioc->request_sz))/1024)); dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool: dma(0x%llx)\n", ioc->name, (unsigned long long) ioc->request_dma)); total_sz += sz; @@ -2255,6 +2269,38 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) "depth(%d)\n", ioc->name, ioc->request, ioc->scsiio_depth)); + /* loop till the allocation succeeds */ + do { + sz = ioc->chain_depth * sizeof(struct chain_tracker); + ioc->chain_pages = get_order(sz); + ioc->chain_lookup = (struct chain_tracker *)__get_free_pages( + GFP_KERNEL, ioc->chain_pages); + if (ioc->chain_lookup == NULL) + ioc->chain_depth -= 100; + } while (ioc->chain_lookup == NULL); + ioc->chain_dma_pool = pci_pool_create("chain pool", ioc->pdev, + ioc->request_sz, 16, 0); + if (!ioc->chain_dma_pool) { + printk(MPT2SAS_ERR_FMT "chain_dma_pool: pci_pool_create " + "failed\n", ioc->name); + goto out; + } + for (i = 0; i < ioc->chain_depth; i++) { + ioc->chain_lookup[i].chain_buffer = pci_pool_alloc( + ioc->chain_dma_pool , GFP_KERNEL, + &ioc->chain_lookup[i].chain_buffer_dma); + if (!ioc->chain_lookup[i].chain_buffer) { + ioc->chain_depth = i; + goto chain_done; + } + total_sz += ioc->request_sz; + } +chain_done: + dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "chain pool depth" + "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, + ioc->chain_depth, ioc->request_sz, ((ioc->chain_depth * + ioc->request_sz))/1024)); + /* initialize hi-priority queue smid's */ ioc->hpr_lookup = kcalloc(ioc->hi_priority_depth, sizeof(struct request_tracker), GFP_KERNEL); @@ -2404,7 +2450,6 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) return 0; out: - _base_release_memory_pools(ioc); return -ENOMEM; } @@ -3587,6 +3632,7 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) INIT_LIST_HEAD(&ioc->free_list); smid = 1; for (i = 0; i < ioc->scsiio_depth; i++, smid++) { + INIT_LIST_HEAD(&ioc->scsi_lookup[i].chain_list); ioc->scsi_lookup[i].cb_idx = 0xFF; ioc->scsi_lookup[i].smid = smid; ioc->scsi_lookup[i].scmd = NULL; @@ -3613,6 +3659,13 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) list_add_tail(&ioc->internal_lookup[i].tracker_list, &ioc->internal_free_list); } + + /* chain pool */ + INIT_LIST_HEAD(&ioc->free_chain_list); + for (i = 0; i < ioc->chain_depth; i++) + list_add_tail(&ioc->chain_lookup[i].tracker_list, + &ioc->free_chain_list); + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); /* initialize Reply Free Queue */ diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index 63f7a196f42d..edf1a028db6c 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -418,6 +418,18 @@ enum reset_type { SOFT_RESET, }; +/** + * struct chain_tracker - firmware chain tracker + * @chain_buffer: chain buffer + * @chain_buffer_dma: physical address + * @tracker_list: list of free request (ioc->free_chain_list) + */ +struct chain_tracker { + void *chain_buffer; + dma_addr_t chain_buffer_dma; + struct list_head tracker_list; +}; + /** * struct request_tracker - firmware request tracker * @smid: system message id @@ -430,6 +442,7 @@ struct request_tracker { u16 smid; struct scsi_cmnd *scmd; u8 cb_idx; + struct list_head chain_list; struct list_head tracker_list; }; @@ -704,8 +717,10 @@ struct MPT2SAS_ADAPTER { wait_queue_head_t reset_wq; /* chain */ - u8 *chain; - dma_addr_t chain_dma; + struct chain_tracker *chain_lookup; + struct list_head free_chain_list; + struct dma_pool *chain_dma_pool; + ulong chain_pages; u16 max_sges_in_main_message; u16 max_sges_in_chain_message; u16 chains_needed_per_io; diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 5af5781d9464..3e9c78aa4ccb 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -931,31 +931,32 @@ _scsih_scsi_lookup_find_by_lun(struct MPT2SAS_ADAPTER *ioc, int id, } /** - * _scsih_get_chain_buffer_dma - obtain block of chains (dma address) + * _scsih_get_chain_buffer_tracker - obtain chain tracker * @ioc: per adapter object - * @smid: system request message index + * @smid: smid associated to an IO request * - * Returns phys pointer to chain buffer. + * Returns chain tracker(from ioc->free_chain_list) */ -static dma_addr_t -_scsih_get_chain_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid) +static struct chain_tracker * +_scsih_get_chain_buffer_tracker(struct MPT2SAS_ADAPTER *ioc, u16 smid) { - return ioc->chain_dma + ((smid - 1) * (ioc->request_sz * - ioc->chains_needed_per_io)); -} + struct chain_tracker *chain_req; + unsigned long flags; -/** - * _scsih_get_chain_buffer - obtain block of chains assigned to a mf request - * @ioc: per adapter object - * @smid: system request message index - * - * Returns virt pointer to chain buffer. - */ -static void * -_scsih_get_chain_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid) -{ - return (void *)(ioc->chain + ((smid - 1) * (ioc->request_sz * - ioc->chains_needed_per_io))); + spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); + if (list_empty(&ioc->free_chain_list)) { + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); + printk(MPT2SAS_WARN_FMT "chain buffers not available\n", + ioc->name); + return NULL; + } + chain_req = list_entry(ioc->free_chain_list.next, + struct chain_tracker, tracker_list); + list_del_init(&chain_req->tracker_list); + list_add_tail(&chain_req->tracker_list, + &ioc->scsi_lookup[smid - 1].chain_list); + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); + return chain_req; } /** @@ -986,6 +987,7 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc, u32 sgl_flags; u32 sgl_flags_last_element; u32 sgl_flags_end_buffer; + struct chain_tracker *chain_req; mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); @@ -1033,8 +1035,11 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc, /* initializing the chain flags and pointers */ chain_flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT << MPI2_SGE_FLAGS_SHIFT; - chain = _scsih_get_chain_buffer(ioc, smid); - chain_dma = _scsih_get_chain_buffer_dma(ioc, smid); + chain_req = _scsih_get_chain_buffer_tracker(ioc, smid); + if (!chain_req) + return -1; + chain = chain_req->chain_buffer; + chain_dma = chain_req->chain_buffer_dma; do { sges_in_segment = (sges_left <= ioc->max_sges_in_chain_message) ? sges_left : @@ -1070,8 +1075,11 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc, sges_in_segment--; } - chain_dma += ioc->request_sz; - chain += ioc->request_sz; + chain_req = _scsih_get_chain_buffer_tracker(ioc, smid); + if (!chain_req) + return -1; + chain = chain_req->chain_buffer; + chain_dma = chain_req->chain_buffer_dma; } while (1); -- cgit v1.2.3-59-g8ed1b From 7f6f794dee50ba33710145140f39de59f5ec764e Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Sat, 13 Nov 2010 04:35:30 +0530 Subject: [SCSI] mpt2sas: Modify code to support Expander switch Issue : Switch swap doesn't work when device missing delay is enabled. (1) add support to individually add and remove phys to and from existing ports. This replaces the routine _transport_delete_duplicate_port. (2) _scsih_sas_host_refresh - was modified to change the link rate from zero to 1.5 GB rate when the firmware reports there is an attached device with zero link. (3) add new function mpt2sas_device_remove, this is wrapper function deletes some redundant code through out driver by combining into one subrountine (4) two subroutines were modified so the sas_device, raid_device, and port lists are traversed once when objects are deleted from the list. Previously it was looping back each time an object was deleted from the list. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.h | 2 + drivers/scsi/mpt2sas/mpt2sas_scsih.c | 143 +++++++++++------------- drivers/scsi/mpt2sas/mpt2sas_transport.c | 185 +++++++++++++++++++++++-------- 3 files changed, 206 insertions(+), 124 deletions(-) diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index edf1a028db6c..428a8c2cf7e0 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -849,6 +849,8 @@ int mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, ulong timeout, struct scsi_cmnd *scmd); void mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle); void mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle); +void mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address); +void mpt2sas_device_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address); struct _sas_node *mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle); struct _sas_node *mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 3e9c78aa4ccb..50c6bdf3fddd 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -2584,9 +2584,9 @@ _scsih_block_io_to_children_attached_to_ex(struct MPT2SAS_ADAPTER *ioc, &sas_expander->sas_port_list, port_list) { if (mpt2sas_port->remote_identify.device_type == - MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER || + SAS_EDGE_EXPANDER_DEVICE || mpt2sas_port->remote_identify.device_type == - MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER) { + SAS_FANOUT_EXPANDER_DEVICE) { spin_lock_irqsave(&ioc->sas_node_lock, flags); expander_sibling = @@ -3972,6 +3972,7 @@ _scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc) Mpi2ConfigReply_t mpi_reply; Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL; u16 attached_handle; + u8 link_rate; dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "updating handles for sas_host(0x%016llx)\n", @@ -3993,15 +3994,17 @@ _scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc) if (ioc_status != MPI2_IOCSTATUS_SUCCESS) goto out; for (i = 0; i < ioc->sas_hba.num_phys ; i++) { + link_rate = sas_iounit_pg0->PhyData[i].NegotiatedLinkRate >> 4; if (i == 0) ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0-> PhyData[0].ControllerDevHandle); ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle; attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i]. AttachedDevHandle); + if (attached_handle && link_rate < MPI2_SAS_NEG_LINK_RATE_1_5) + link_rate = MPI2_SAS_NEG_LINK_RATE_1_5; mpt2sas_transport_update_links(ioc, ioc->sas_hba.sas_address, - attached_handle, i, sas_iounit_pg0->PhyData[i]. - NegotiatedLinkRate >> 4); + attached_handle, i, link_rate); } out: kfree(sas_iounit_pg0); @@ -4345,14 +4348,14 @@ _scsih_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) } /** - * _scsih_expander_remove - removing expander object + * mpt2sas_expander_remove - removing expander object * @ioc: per adapter object * @sas_address: expander sas_address * * Return nothing. */ -static void -_scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address) +void +mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address) { struct _sas_node *sas_expander; unsigned long flags; @@ -4363,6 +4366,11 @@ _scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address) spin_lock_irqsave(&ioc->sas_node_lock, flags); sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc, sas_address); + if (!sas_expander) { + spin_unlock_irqrestore(&ioc->sas_node_lock, flags); + return; + } + list_del(&sas_expander->list); spin_unlock_irqrestore(&ioc->sas_node_lock, flags); _scsih_expander_node_remove(ioc, sas_expander); } @@ -4652,6 +4660,33 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, sas_device_backup.sas_address)); } +/** + * mpt2sas_device_remove - removing device object + * @ioc: per adapter object + * @sas_address: expander sas_address + * + * Return nothing. + */ +void +mpt2sas_device_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address) +{ + struct _sas_device *sas_device; + unsigned long flags; + + if (ioc->shost_recovery) + return; + + spin_lock_irqsave(&ioc->sas_device_lock, flags); + sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, + sas_address); + if (!sas_device) { + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + return; + } + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + _scsih_remove_device(ioc, sas_device); +} + #ifdef CONFIG_SCSI_MPT2SAS_LOGGING /** * _scsih_sas_topology_change_event_debug - debug for topology event @@ -4853,7 +4888,7 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, /* handle expander removal */ if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING && sas_expander) - _scsih_expander_remove(ioc, sas_address); + mpt2sas_expander_remove(ioc, sas_address); } @@ -6228,7 +6263,7 @@ _scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc) sas_expander->responding = 0; continue; } - _scsih_expander_remove(ioc, sas_expander->sas_address); + mpt2sas_expander_remove(ioc, sas_expander->sas_address); goto retry_expander_search; } } @@ -6499,56 +6534,23 @@ static void _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc, struct _sas_node *sas_expander) { - struct _sas_port *mpt2sas_port; - struct _sas_device *sas_device; - struct _sas_node *expander_sibling; - unsigned long flags; - - if (!sas_expander) - return; + struct _sas_port *mpt2sas_port, *next; /* remove sibling ports attached to this expander */ - retry_device_search: - list_for_each_entry(mpt2sas_port, - &sas_expander->sas_port_list, port_list) { - if (mpt2sas_port->remote_identify.device_type == - SAS_END_DEVICE) { - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = - mpt2sas_scsih_sas_device_find_by_sas_address(ioc, - mpt2sas_port->remote_identify.sas_address); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - if (!sas_device) - continue; - _scsih_remove_device(ioc, sas_device); - if (ioc->shost_recovery) - return; - goto retry_device_search; - } - } - - retry_expander_search: - list_for_each_entry(mpt2sas_port, + list_for_each_entry_safe(mpt2sas_port, next, &sas_expander->sas_port_list, port_list) { - + if (ioc->shost_recovery) + return; if (mpt2sas_port->remote_identify.device_type == - MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER || + SAS_END_DEVICE) + mpt2sas_device_remove(ioc, + mpt2sas_port->remote_identify.sas_address); + else if (mpt2sas_port->remote_identify.device_type == + SAS_EDGE_EXPANDER_DEVICE || mpt2sas_port->remote_identify.device_type == - MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER) { - - spin_lock_irqsave(&ioc->sas_node_lock, flags); - expander_sibling = - mpt2sas_scsih_expander_find_by_sas_address( - ioc, mpt2sas_port->remote_identify.sas_address); - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - if (!expander_sibling) - continue; - _scsih_expander_remove(ioc, - expander_sibling->sas_address); - if (ioc->shost_recovery) - return; - goto retry_expander_search; - } + SAS_FANOUT_EXPANDER_DEVICE) + mpt2sas_expander_remove(ioc, + mpt2sas_port->remote_identify.sas_address); } mpt2sas_transport_port_remove(ioc, sas_expander->sas_address, @@ -6559,7 +6561,6 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc, sas_expander->handle, (unsigned long long) sas_expander->sas_address); - list_del(&sas_expander->list); kfree(sas_expander->phy); kfree(sas_expander); } @@ -6677,9 +6678,7 @@ _scsih_remove(struct pci_dev *pdev) { struct Scsi_Host *shost = pci_get_drvdata(pdev); struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); - struct _sas_port *mpt2sas_port; - struct _sas_device *sas_device; - struct _sas_node *expander_sibling; + struct _sas_port *mpt2sas_port, *next_port; struct _raid_device *raid_device, *next; struct MPT2SAS_TARGET *sas_target_priv_data; struct workqueue_struct *wq; @@ -6711,28 +6710,18 @@ _scsih_remove(struct pci_dev *pdev) } /* free ports attached to the sas_host */ - retry_again: - list_for_each_entry(mpt2sas_port, + list_for_each_entry_safe(mpt2sas_port, next_port, &ioc->sas_hba.sas_port_list, port_list) { if (mpt2sas_port->remote_identify.device_type == - SAS_END_DEVICE) { - sas_device = - mpt2sas_scsih_sas_device_find_by_sas_address(ioc, - mpt2sas_port->remote_identify.sas_address); - if (sas_device) { - _scsih_remove_device(ioc, sas_device); - goto retry_again; - } - } else { - expander_sibling = - mpt2sas_scsih_expander_find_by_sas_address(ioc, + SAS_END_DEVICE) + mpt2sas_device_remove(ioc, + mpt2sas_port->remote_identify.sas_address); + else if (mpt2sas_port->remote_identify.device_type == + SAS_EDGE_EXPANDER_DEVICE || + mpt2sas_port->remote_identify.device_type == + SAS_FANOUT_EXPANDER_DEVICE) + mpt2sas_expander_remove(ioc, mpt2sas_port->remote_identify.sas_address); - if (expander_sibling) { - _scsih_expander_remove(ioc, - expander_sibling->sas_address); - goto retry_again; - } - } } /* free phys attached to the sas_host */ diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c index b55c6dc07470..cb1cdecbe0f8 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_transport.c +++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c @@ -465,62 +465,149 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc, return rc; } +/** + * _transport_delete_port - helper function to removing a port + * @ioc: per adapter object + * @mpt2sas_port: mpt2sas per port object + * + * Returns nothing. + */ +static void +_transport_delete_port(struct MPT2SAS_ADAPTER *ioc, + struct _sas_port *mpt2sas_port) +{ + u64 sas_address = mpt2sas_port->remote_identify.sas_address; + enum sas_device_type device_type = + mpt2sas_port->remote_identify.device_type; + + dev_printk(KERN_INFO, &mpt2sas_port->port->dev, + "remove: sas_addr(0x%016llx)\n", + (unsigned long long) sas_address); + + ioc->logging_level |= MPT_DEBUG_TRANSPORT; + if (device_type == SAS_END_DEVICE) + mpt2sas_device_remove(ioc, sas_address); + else if (device_type == SAS_EDGE_EXPANDER_DEVICE || + device_type == SAS_FANOUT_EXPANDER_DEVICE) + mpt2sas_expander_remove(ioc, sas_address); + ioc->logging_level &= ~MPT_DEBUG_TRANSPORT; +} /** - * _transport_delete_duplicate_port - (see below description) + * _transport_delete_phy - helper function to removing single phy from port * @ioc: per adapter object - * @sas_node: sas node object (either expander or sas host) - * @sas_address: sas address of device being added - * @phy_num: phy number + * @mpt2sas_port: mpt2sas per port object + * @mpt2sas_phy: mpt2sas per phy object * - * This function is called when attempting to add a new port that is claiming - * the same phy resources already in use by another port. If we don't release - * the claimed phy resources, the sas transport layer will hang from the BUG - * in sas_port_add_phy. + * Returns nothing. + */ +static void +_transport_delete_phy(struct MPT2SAS_ADAPTER *ioc, + struct _sas_port *mpt2sas_port, struct _sas_phy *mpt2sas_phy) +{ + u64 sas_address = mpt2sas_port->remote_identify.sas_address; + + dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev, + "remove: sas_addr(0x%016llx), phy(%d)\n", + (unsigned long long) sas_address, mpt2sas_phy->phy_id); + + list_del(&mpt2sas_phy->port_siblings); + mpt2sas_port->num_phys--; + sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy); + mpt2sas_phy->phy_belongs_to_port = 0; +} + +/** + * _transport_add_phy - helper function to adding single phy to port + * @ioc: per adapter object + * @mpt2sas_port: mpt2sas per port object + * @mpt2sas_phy: mpt2sas per phy object * - * The reason we would hit this issue is becuase someone is changing the - * sas address of a device on the fly, meanwhile controller firmware sends - * EVENTs out of order when removing the previous instance of the device. + * Returns nothing. */ static void -_transport_delete_duplicate_port(struct MPT2SAS_ADAPTER *ioc, - struct _sas_node *sas_node, u64 sas_address, int phy_num) +_transport_add_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_port *mpt2sas_port, + struct _sas_phy *mpt2sas_phy) { - struct _sas_port *mpt2sas_port, *mpt2sas_port_duplicate; - struct _sas_phy *mpt2sas_phy; + u64 sas_address = mpt2sas_port->remote_identify.sas_address; - printk(MPT2SAS_ERR_FMT "new device located at sas_addr(0x%016llx), " - "phy_id(%d)\n", ioc->name, (unsigned long long)sas_address, - phy_num); + dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev, + "add: sas_addr(0x%016llx), phy(%d)\n", (unsigned long long) + sas_address, mpt2sas_phy->phy_id); - mpt2sas_port_duplicate = NULL; - list_for_each_entry(mpt2sas_port, &sas_node->sas_port_list, port_list) { - dev_printk(KERN_ERR, &mpt2sas_port->port->dev, - "existing device at sas_addr(0x%016llx), num_phys(%d)\n", - (unsigned long long) - mpt2sas_port->remote_identify.sas_address, - mpt2sas_port->num_phys); - list_for_each_entry(mpt2sas_phy, &mpt2sas_port->phy_list, + list_add_tail(&mpt2sas_phy->port_siblings, &mpt2sas_port->phy_list); + mpt2sas_port->num_phys++; + sas_port_add_phy(mpt2sas_port->port, mpt2sas_phy->phy); + mpt2sas_phy->phy_belongs_to_port = 1; +} + +/** + * _transport_add_phy_to_an_existing_port - adding new phy to existing port + * @ioc: per adapter object + * @sas_node: sas node object (either expander or sas host) + * @mpt2sas_phy: mpt2sas per phy object + * @sas_address: sas address of device/expander were phy needs to be added to + * + * Returns nothing. + */ +static void +_transport_add_phy_to_an_existing_port(struct MPT2SAS_ADAPTER *ioc, +struct _sas_node *sas_node, struct _sas_phy *mpt2sas_phy, u64 sas_address) +{ + struct _sas_port *mpt2sas_port; + struct _sas_phy *phy_srch; + + if (mpt2sas_phy->phy_belongs_to_port == 1) + return; + + list_for_each_entry(mpt2sas_port, &sas_node->sas_port_list, + port_list) { + if (mpt2sas_port->remote_identify.sas_address != + sas_address) + continue; + list_for_each_entry(phy_srch, &mpt2sas_port->phy_list, port_siblings) { - dev_printk(KERN_ERR, &mpt2sas_phy->phy->dev, - "phy_number(%d)\n", mpt2sas_phy->phy_id); - if (mpt2sas_phy->phy_id == phy_num) - mpt2sas_port_duplicate = mpt2sas_port; + if (phy_srch == mpt2sas_phy) + return; } + _transport_add_phy(ioc, mpt2sas_port, mpt2sas_phy); + return; } - if (!mpt2sas_port_duplicate) +} + +/** + * _transport_del_phy_from_an_existing_port - delete phy from existing port + * @ioc: per adapter object + * @sas_node: sas node object (either expander or sas host) + * @mpt2sas_phy: mpt2sas per phy object + * + * Returns nothing. + */ +static void +_transport_del_phy_from_an_existing_port(struct MPT2SAS_ADAPTER *ioc, + struct _sas_node *sas_node, struct _sas_phy *mpt2sas_phy) +{ + struct _sas_port *mpt2sas_port, *next; + struct _sas_phy *phy_srch; + + if (mpt2sas_phy->phy_belongs_to_port == 0) return; - dev_printk(KERN_ERR, &mpt2sas_port_duplicate->port->dev, - "deleting duplicate device at sas_addr(0x%016llx), phy(%d)!!!!\n", - (unsigned long long) - mpt2sas_port_duplicate->remote_identify.sas_address, phy_num); - ioc->logging_level |= MPT_DEBUG_TRANSPORT; - mpt2sas_transport_port_remove(ioc, - mpt2sas_port_duplicate->remote_identify.sas_address, - sas_node->sas_address); - ioc->logging_level &= ~MPT_DEBUG_TRANSPORT; + list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list, + port_list) { + list_for_each_entry(phy_srch, &mpt2sas_port->phy_list, + port_siblings) { + if (phy_srch != mpt2sas_phy) + continue; + if (mpt2sas_port->num_phys == 1) + _transport_delete_port(ioc, mpt2sas_port); + else + _transport_delete_phy(ioc, mpt2sas_port, + mpt2sas_phy); + return; + } + } } /** @@ -537,11 +624,13 @@ _transport_sanity_check(struct MPT2SAS_ADAPTER *ioc, struct _sas_node *sas_node, { int i; - for (i = 0; i < sas_node->num_phys; i++) - if (sas_node->phy[i].remote_identify.sas_address == sas_address) - if (sas_node->phy[i].phy_belongs_to_port) - _transport_delete_duplicate_port(ioc, sas_node, - sas_address, i); + for (i = 0; i < sas_node->num_phys; i++) { + if (sas_node->phy[i].remote_identify.sas_address != sas_address) + continue; + if (sas_node->phy[i].phy_belongs_to_port == 1) + _transport_del_phy_from_an_existing_port(ioc, sas_node, + &sas_node->phy[i]); + } } /** @@ -905,10 +994,12 @@ mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc, mpt2sas_phy = &sas_node->phy[phy_number]; mpt2sas_phy->attached_handle = handle; - if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) + if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) { _transport_set_identify(ioc, handle, &mpt2sas_phy->remote_identify); - else + _transport_add_phy_to_an_existing_port(ioc, sas_node, + mpt2sas_phy, mpt2sas_phy->remote_identify.sas_address); + } else memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct sas_identify)); -- cgit v1.2.3-59-g8ed1b From 7d061402590efc37d553a9155dbf41277675c179 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Sat, 13 Nov 2010 04:36:14 +0530 Subject: [SCSI] mpt2sas: MPI 2.0 Header updated MPI2 Rev header files. 1) Removed Task Set Full Event. Modified description of Disable SCSI Initiator Task Set Full Handling bit in the Flags field of IO Unit Page 1. Modified the descriptions for the three queue depth fields in SAS IO Unit Page 1. (2) Added new value for the Current Operation bits of the Flags field in the RAID Volume Indicator Structure to indicate that the Make Data Consistent operation is running. (3) Added a value of 0x6 to various SAS link rate fields to indicate an attached PHY that is not using any commonly supported settings. (4) Added Volume Not Consistent bit to the VolumeStatusFlags field of RAID Volume Page 0. (5) Added a new value for the IncompatibleReason field of RAID Physical Disk Page 0 to indicate an incompatible media type. (6) Added Diagnostic Data Upload tool for the Toolbox Request. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpi/mpi2.h | 9 ++++-- drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h | 20 +++++++++++-- drivers/scsi/mpt2sas/mpi/mpi2_history.txt | 3 ++ drivers/scsi/mpt2sas/mpi/mpi2_init.h | 9 +++++- drivers/scsi/mpt2sas/mpi/mpi2_ioc.h | 8 +++-- drivers/scsi/mpt2sas/mpi/mpi2_raid.h | 6 ++-- drivers/scsi/mpt2sas/mpi/mpi2_sas.h | 9 +++--- drivers/scsi/mpt2sas/mpi/mpi2_tool.h | 49 +++++++++++++++++++++++++++---- 8 files changed, 95 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/mpt2sas/mpi/mpi2.h b/drivers/scsi/mpt2sas/mpi/mpi2.h index 4b1c2f0350f9..8be75e65f763 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2.h @@ -8,7 +8,7 @@ * scatter/gather formats. * Creation Date: June 21, 2006 * - * mpi2.h Version: 02.00.15 + * mpi2.h Version: 02.00.16 * * Version History * --------------- @@ -61,6 +61,8 @@ * Added define for MPI2_FUNCTION_PWR_MGMT_CONTROL. * Added defines for product-specific range of message * function codes, 0xF0 to 0xFF. + * 05-12-10 02.00.16 Bumped MPI2_HEADER_VERSION_UNIT. + * Added alternative defines for the SGE Direction bit. * -------------------------------------------------------------------------- */ @@ -86,7 +88,7 @@ #define MPI2_VERSION_02_00 (0x0200) /* versioning for this MPI header set */ -#define MPI2_HEADER_VERSION_UNIT (0x0F) +#define MPI2_HEADER_VERSION_UNIT (0x10) #define MPI2_HEADER_VERSION_DEV (0x00) #define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00) #define MPI2_HEADER_VERSION_UNIT_SHIFT (8) @@ -929,6 +931,9 @@ typedef struct _MPI2_MPI_SGE_UNION #define MPI2_SGE_FLAGS_IOC_TO_HOST (0x00) #define MPI2_SGE_FLAGS_HOST_TO_IOC (0x04) +#define MPI2_SGE_FLAGS_DEST (MPI2_SGE_FLAGS_IOC_TO_HOST) +#define MPI2_SGE_FLAGS_SOURCE (MPI2_SGE_FLAGS_HOST_TO_IOC) + /* Address Size */ #define MPI2_SGE_FLAGS_32_BIT_ADDRESSING (0x00) diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h index e3728d736d85..d76a65847603 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h @@ -6,7 +6,7 @@ * Title: MPI Configuration messages and pages * Creation Date: November 10, 2006 * - * mpi2_cnfg.h Version: 02.00.14 + * mpi2_cnfg.h Version: 02.00.15 * * Version History * --------------- @@ -121,6 +121,10 @@ * Added MPI2_CONFIG_PAGE_SASIOUNIT_6 and related defines. * Added MPI2_CONFIG_PAGE_SASIOUNIT_7 and related defines. * Added MPI2_CONFIG_PAGE_SASIOUNIT_8 and related defines. + * 05-12-10 02.00.15 Added MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT + * define. + * Added MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE define. + * Added MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY define. * -------------------------------------------------------------------------- */ @@ -333,7 +337,7 @@ typedef struct _MPI2_CONFIG_REQUEST #define MPI2_CONFIG_ACTION_PAGE_READ_NVRAM (0x06) #define MPI2_CONFIG_ACTION_PAGE_GET_CHANGEABLE (0x07) -/* values for SGLFlags field are in the SGL section of mpi2.h */ +/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ /* Config Reply Message */ @@ -379,6 +383,8 @@ typedef struct _MPI2_CONFIG_REPLY #define MPI2_MFGPAGE_DEVID_SAS2116_1 (0x0064) #define MPI2_MFGPAGE_DEVID_SAS2116_2 (0x0065) +#define MPI2_MFGPAGE_DEVID_SSS6200 (0x007E) + #define MPI2_MFGPAGE_DEVID_SAS2208_1 (0x0080) #define MPI2_MFGPAGE_DEVID_SAS2208_2 (0x0081) #define MPI2_MFGPAGE_DEVID_SAS2208_3 (0x0082) @@ -390,6 +396,8 @@ typedef struct _MPI2_CONFIG_REPLY #define MPI2_MFGPAGE_DEVID_SAS2308_3 (0x006E) + + /* Manufacturing Page 0 */ typedef struct _MPI2_CONFIG_PAGE_MAN_0 @@ -729,6 +737,7 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_1 /* IO Unit Page 1 Flags defines */ #define MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY (0x00000800) #define MPI2_IOUNITPAGE1_MASK_SATA_WRITE_CACHE (0x00000600) +#define MPI2_IOUNITPAGE1_SATA_WRITE_CACHE_SHIFT (9) #define MPI2_IOUNITPAGE1_ENABLE_SATA_WRITE_CACHE (0x00000000) #define MPI2_IOUNITPAGE1_DISABLE_SATA_WRITE_CACHE (0x00000200) #define MPI2_IOUNITPAGE1_UNCHANGED_SATA_WRITE_CACHE (0x00000400) @@ -1347,6 +1356,7 @@ typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_0 #define MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION (0x00040000) #define MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT (0x00020000) #define MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS (0x00010000) +#define MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT (0x00000080) #define MPI2_RAIDVOL0_STATUS_FLAG_OCE_ALLOWED (0x00000040) #define MPI2_RAIDVOL0_STATUS_FLAG_BGI_COMPLETE (0x00000020) #define MPI2_RAIDVOL0_STATUS_FLAG_1E_OFFSET_MIRROR (0x00000000) @@ -1469,11 +1479,15 @@ typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_0 #define MPI2_PHYSDISK0_INCOMPATIBLE_MAX_LBA (0x03) #define MPI2_PHYSDISK0_INCOMPATIBLE_SATA_EXTENDED_CMD (0x04) #define MPI2_PHYSDISK0_INCOMPATIBLE_REMOVEABLE_MEDIA (0x05) +#define MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE (0x06) #define MPI2_PHYSDISK0_INCOMPATIBLE_UNKNOWN (0xFF) /* PhysDiskAttributes defines */ +#define MPI2_PHYSDISK0_ATTRIB_MEDIA_MASK (0x0C) #define MPI2_PHYSDISK0_ATTRIB_SOLID_STATE_DRIVE (0x08) #define MPI2_PHYSDISK0_ATTRIB_HARD_DISK_DRIVE (0x04) + +#define MPI2_PHYSDISK0_ATTRIB_PROTOCOL_MASK (0x03) #define MPI2_PHYSDISK0_ATTRIB_SAS_PROTOCOL (0x02) #define MPI2_PHYSDISK0_ATTRIB_SATA_PROTOCOL (0x01) @@ -1545,6 +1559,7 @@ typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1 #define MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE (0x03) #define MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR (0x04) #define MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS (0x05) +#define MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY (0x06) #define MPI2_SAS_NEG_LINK_RATE_1_5 (0x08) #define MPI2_SAS_NEG_LINK_RATE_3_0 (0x09) #define MPI2_SAS_NEG_LINK_RATE_6_0 (0x0A) @@ -1571,6 +1586,7 @@ typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1 #define MPI2_SAS_PHYINFO_PHY_VACANT (0x80000000) #define MPI2_SAS_PHYINFO_PHY_POWER_CONDITION_MASK (0x18000000) +#define MPI2_SAS_PHYINFO_SHIFT_PHY_POWER_CONDITION (27) #define MPI2_SAS_PHYINFO_PHY_POWER_ACTIVE (0x00000000) #define MPI2_SAS_PHYINFO_PHY_POWER_PARTIAL (0x08000000) #define MPI2_SAS_PHYINFO_PHY_POWER_SLUMBER (0x10000000) diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_history.txt b/drivers/scsi/mpt2sas/mpi/mpi2_history.txt index bd6c92b5fae5..b1e88f26b748 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2_history.txt +++ b/drivers/scsi/mpt2sas/mpi/mpi2_history.txt @@ -291,6 +291,7 @@ mpi2_raid.h * can be sized by the build environment. * 07-30-09 02.00.04 Added proper define for the Use Default Settings bit of * VolumeCreationFlags and marked the old one as obsolete. + * 05-12-10 02.00.05 Added MPI2_RAID_VOL_FLAGS_OP_MDC define. * -------------------------------------------------------------------------- mpi2_sas.h @@ -301,6 +302,7 @@ mpi2_sas.h * Request. * 10-28-09 02.00.03 Changed the type of SGL in MPI2_SATA_PASSTHROUGH_REQUEST * to MPI2_SGE_IO_UNION since it supports chained SGLs. + * 05-12-10 02.00.04 Modified some comments. * -------------------------------------------------------------------------- mpi2_targ.h @@ -324,6 +326,7 @@ mpi2_tool.h * and reply messages. * Added MPI2_DIAG_BUF_TYPE_EXTENDED. * Incremented MPI2_DIAG_BUF_TYPE_COUNT. + * 05-12-10 02.00.05 Added Diagnostic Data Upload tool. * -------------------------------------------------------------------------- mpi2_type.h diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_init.h b/drivers/scsi/mpt2sas/mpi/mpi2_init.h index c4c99dfcb820..20e6b8869341 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2_init.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2_init.h @@ -6,7 +6,7 @@ * Title: MPI SCSI initiator mode messages and structures * Creation Date: June 23, 2006 * - * mpi2_init.h Version: 02.00.09 + * mpi2_init.h Version: 02.00.10 * * Version History * --------------- @@ -32,6 +32,7 @@ * Added ResponseInfo field to MPI2_SCSI_TASK_MANAGE_REPLY. * Added MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG define. * 02-10-10 02.00.09 Removed unused structure that had "#if 0" around it. + * 05-12-10 02.00.10 Added optional vendor-unique region to SCSI IO Request. * -------------------------------------------------------------------------- */ @@ -98,7 +99,13 @@ typedef struct _MPI2_SCSI_IO_REQUEST U8 LUN[8]; /* 0x34 */ U32 Control; /* 0x3C */ MPI2_SCSI_IO_CDB_UNION CDB; /* 0x40 */ + +#ifdef MPI2_SCSI_IO_VENDOR_UNIQUE_REGION /* typically this is left undefined */ + MPI2_SCSI_IO_VENDOR_UNIQUE VendorRegion; +#endif + MPI2_SGE_IO_UNION SGL; /* 0x60 */ + } MPI2_SCSI_IO_REQUEST, MPI2_POINTER PTR_MPI2_SCSI_IO_REQUEST, Mpi2SCSIIORequest_t, MPI2_POINTER pMpi2SCSIIORequest_t; diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h index 495bedc4d1f7..761cbdb8a033 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h @@ -6,7 +6,7 @@ * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages * Creation Date: October 11, 2006 * - * mpi2_ioc.h Version: 02.00.14 + * mpi2_ioc.h Version: 02.00.15 * * Version History * --------------- @@ -101,6 +101,8 @@ * 02-10-10 02.00.14 Added SAS Quiesce Event structure and defines. * Added PowerManagementControl Request structures and * defines. + * 05-12-10 02.00.15 Marked Task Set Full Event as obsolete. + * Added MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY define. * -------------------------------------------------------------------------- */ @@ -456,7 +458,7 @@ typedef struct _MPI2_EVENT_NOTIFICATION_REPLY #define MPI2_EVENT_STATE_CHANGE (0x0002) #define MPI2_EVENT_HARD_RESET_RECEIVED (0x0005) #define MPI2_EVENT_EVENT_CHANGE (0x000A) -#define MPI2_EVENT_TASK_SET_FULL (0x000E) +#define MPI2_EVENT_TASK_SET_FULL (0x000E) /* obsolete */ #define MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE (0x000F) #define MPI2_EVENT_IR_OPERATION_STATUS (0x0014) #define MPI2_EVENT_SAS_DISCOVERY (0x0016) @@ -517,6 +519,7 @@ typedef struct _MPI2_EVENT_DATA_HARD_RESET_RECEIVED MPI2_POINTER pMpi2EventDataHardResetReceived_t; /* Task Set Full Event data */ +/* this event is obsolete */ typedef struct _MPI2_EVENT_DATA_TASK_SET_FULL { @@ -831,6 +834,7 @@ typedef struct _MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST #define MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE (0x03) #define MPI2_EVENT_SAS_TOPO_LR_PORT_SELECTOR (0x04) #define MPI2_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS (0x05) +#define MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY (0x06) #define MPI2_EVENT_SAS_TOPO_LR_RATE_1_5 (0x08) #define MPI2_EVENT_SAS_TOPO_LR_RATE_3_0 (0x09) #define MPI2_EVENT_SAS_TOPO_LR_RATE_6_0 (0x0A) diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_raid.h b/drivers/scsi/mpt2sas/mpi/mpi2_raid.h index 5160c33d2a00..bd61a7b60a2b 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2_raid.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2_raid.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2008 LSI Corporation. + * Copyright (c) 2000-2010 LSI Corporation. * * * Name: mpi2_raid.h * Title: MPI Integrated RAID messages and structures * Creation Date: April 26, 2007 * - * mpi2_raid.h Version: 02.00.04 + * mpi2_raid.h Version: 02.00.05 * * Version History * --------------- @@ -22,6 +22,7 @@ * can be sized by the build environment. * 07-30-09 02.00.04 Added proper define for the Use Default Settings bit of * VolumeCreationFlags and marked the old one as obsolete. + * 05-12-10 02.00.05 Added MPI2_RAID_VOL_FLAGS_OP_MDC define. * -------------------------------------------------------------------------- */ @@ -260,6 +261,7 @@ typedef struct _MPI2_RAID_VOL_INDICATOR #define MPI2_RAID_VOL_FLAGS_OP_ONLINE_CAP_EXPANSION (0x00000001) #define MPI2_RAID_VOL_FLAGS_OP_CONSISTENCY_CHECK (0x00000002) #define MPI2_RAID_VOL_FLAGS_OP_RESYNC (0x00000003) +#define MPI2_RAID_VOL_FLAGS_OP_MDC (0x00000004) /* RAID Action Reply ActionData union */ diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_sas.h b/drivers/scsi/mpt2sas/mpi/mpi2_sas.h index 2d8aeed51392..608f6d6e6fca 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2_sas.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2_sas.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2007 LSI Corporation. + * Copyright (c) 2000-2010 LSI Corporation. * * * Name: mpi2_sas.h * Title: MPI Serial Attached SCSI structures and definitions * Creation Date: February 9, 2007 * - * mpi2.h Version: 02.00.03 + * mpi2_sas.h Version: 02.00.04 * * Version History * --------------- @@ -20,6 +20,7 @@ * Request. * 10-28-09 02.00.03 Changed the type of SGL in MPI2_SATA_PASSTHROUGH_REQUEST * to MPI2_SGE_IO_UNION since it supports chained SGLs. + * 05-12-10 02.00.04 Modified some comments. * -------------------------------------------------------------------------- */ @@ -110,7 +111,7 @@ typedef struct _MPI2_SMP_PASSTHROUGH_REQUEST /* values for PassthroughFlags field */ #define MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE (0x80) -/* values for SGLFlags field are in the SGL section of mpi2.h */ +/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ /* SMP Passthrough Reply Message */ @@ -174,7 +175,7 @@ typedef struct _MPI2_SATA_PASSTHROUGH_REQUEST #define MPI2_SATA_PT_REQ_PT_FLAGS_WRITE (0x0002) #define MPI2_SATA_PT_REQ_PT_FLAGS_READ (0x0001) -/* values for SGLFlags field are in the SGL section of mpi2.h */ +/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ /* SATA Passthrough Reply Message */ diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_tool.h b/drivers/scsi/mpt2sas/mpi/mpi2_tool.h index 686b09b81219..5c6e3a67bb94 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2_tool.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2_tool.h @@ -6,7 +6,7 @@ * Title: MPI diagnostic tool structures and definitions * Creation Date: March 26, 2007 * - * mpi2_tool.h Version: 02.00.04 + * mpi2_tool.h Version: 02.00.05 * * Version History * --------------- @@ -22,6 +22,7 @@ * and reply messages. * Added MPI2_DIAG_BUF_TYPE_EXTENDED. * Incremented MPI2_DIAG_BUF_TYPE_COUNT. + * 05-12-10 02.00.05 Added Diagnostic Data Upload tool. * -------------------------------------------------------------------------- */ @@ -37,6 +38,7 @@ /* defines for the Tools */ #define MPI2_TOOLBOX_CLEAN_TOOL (0x00) #define MPI2_TOOLBOX_MEMORY_MOVE_TOOL (0x01) +#define MPI2_TOOLBOX_DIAG_DATA_UPLOAD_TOOL (0x02) #define MPI2_TOOLBOX_ISTWI_READ_WRITE_TOOL (0x03) #define MPI2_TOOLBOX_BEACON_TOOL (0x05) #define MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL (0x06) @@ -102,8 +104,7 @@ typedef struct _MPI2_TOOLBOX_CLEAN_REQUEST * Toolbox Memory Move request ****************************************************************************/ -typedef struct _MPI2_TOOLBOX_MEM_MOVE_REQUEST -{ +typedef struct _MPI2_TOOLBOX_MEM_MOVE_REQUEST { U8 Tool; /* 0x00 */ U8 Reserved1; /* 0x01 */ U8 ChainOffset; /* 0x02 */ @@ -119,6 +120,44 @@ typedef struct _MPI2_TOOLBOX_MEM_MOVE_REQUEST Mpi2ToolboxMemMoveRequest_t, MPI2_POINTER pMpi2ToolboxMemMoveRequest_t; +/**************************************************************************** +* Toolbox Diagnostic Data Upload request +****************************************************************************/ + +typedef struct _MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST { + U8 Tool; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 Reserved2; /* 0x04 */ + U8 Reserved3; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved4; /* 0x0A */ + U8 SGLFlags; /* 0x0C */ + U8 Reserved5; /* 0x0D */ + U16 Reserved6; /* 0x0E */ + U32 Flags; /* 0x10 */ + U32 DataLength; /* 0x14 */ + MPI2_SGE_SIMPLE_UNION SGL; /* 0x18 */ +} MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST, +MPI2_POINTER PTR_MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST, +Mpi2ToolboxDiagDataUploadRequest_t, +MPI2_POINTER pMpi2ToolboxDiagDataUploadRequest_t; + +/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ + + +typedef struct _MPI2_DIAG_DATA_UPLOAD_HEADER { + U32 DiagDataLength; /* 00h */ + U8 FormatCode; /* 04h */ + U8 Reserved1; /* 05h */ + U16 Reserved2; /* 06h */ +} MPI2_DIAG_DATA_UPLOAD_HEADER, MPI2_POINTER PTR_MPI2_DIAG_DATA_UPLOAD_HEADER, +Mpi2DiagDataUploadHeader_t, MPI2_POINTER pMpi2DiagDataUploadHeader_t; + + /**************************************************************************** * Toolbox ISTWI Read Write Tool ****************************************************************************/ @@ -162,7 +201,7 @@ typedef struct _MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST { #define MPI2_TOOL_ISTWI_ACTION_RELEASE_BUS (0x11) #define MPI2_TOOL_ISTWI_ACTION_RESET (0x12) -/* values for SGLFlags field are in the SGL section of mpi2.h */ +/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ /* Toolbox ISTWI Read Write Tool reply message */ @@ -248,7 +287,7 @@ typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST { Mpi2ToolboxDiagnosticCliRequest_t, MPI2_POINTER pMpi2ToolboxDiagnosticCliRequest_t; -/* values for SGLFlags field are in the SGL section of mpi2.h */ +/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ /* Toolbox Diagnostic CLI Tool reply message */ -- cgit v1.2.3-59-g8ed1b From 90d2a672250b9d6e5c700f2d2c07c19d6fad064a Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Sat, 13 Nov 2010 04:37:36 +0530 Subject: [SCSI] mpt2sas: Remove code for TASK_SET_FULL from driver. remove support for MPI2_EVENT_TASK_SET_FULL This event is obsoleted, so this processing of this event needs to be removed from the driver. The controller firmware is going to handle TASK_SET_FULL, the driver doesn't need to do anything. Even though we are removing the EVENT handling, the behavour has not changed between driver versions becuase fimrware will still be handling queue throttling, and retrying of commands when the target device queues are full. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.c | 4 -- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 88 ------------------------------------ 2 files changed, 92 deletions(-) diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index c8f39f8c6fed..b2a817055b8b 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -518,9 +518,6 @@ _base_display_event_data(struct MPT2SAS_ADAPTER *ioc, case MPI2_EVENT_EVENT_CHANGE: desc = "Event Change"; break; - case MPI2_EVENT_TASK_SET_FULL: - desc = "Task Set Full"; - break; case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: desc = "Device Status Change"; break; @@ -3863,7 +3860,6 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) _base_unmask_events(ioc, MPI2_EVENT_IR_VOLUME); _base_unmask_events(ioc, MPI2_EVENT_IR_PHYSICAL_DISK); _base_unmask_events(ioc, MPI2_EVENT_IR_OPERATION_STATUS); - _base_unmask_events(ioc, MPI2_EVENT_TASK_SET_FULL); _base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED); r = _base_make_ioc_operational(ioc, CAN_SLEEP); if (r) diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 50c6bdf3fddd..e4987dbbaa50 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -5816,90 +5816,6 @@ _scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc, } } -/** - * _scsih_task_set_full - handle task set full - * @ioc: per adapter object - * @fw_event: The fw_event_work object - * Context: user. - * - * Throttle back qdepth. - */ -static void -_scsih_task_set_full(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work - *fw_event) -{ - unsigned long flags; - struct _sas_device *sas_device; - static struct _raid_device *raid_device; - struct scsi_device *sdev; - int depth; - u16 current_depth; - u16 handle; - int id, channel; - u64 sas_address; - Mpi2EventDataTaskSetFull_t *event_data = fw_event->event_data; - - current_depth = le16_to_cpu(event_data->CurrentDepth); - handle = le16_to_cpu(event_data->DevHandle); - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = _scsih_sas_device_find_by_handle(ioc, handle); - if (!sas_device) { - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - return; - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - id = sas_device->id; - channel = sas_device->channel; - sas_address = sas_device->sas_address; - - /* if hidden raid component, then change to volume characteristics */ - if (test_bit(handle, ioc->pd_handles) && sas_device->volume_handle) { - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = _scsih_raid_device_find_by_handle( - ioc, sas_device->volume_handle); - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - if (raid_device) { - id = raid_device->id; - channel = raid_device->channel; - handle = raid_device->handle; - sas_address = raid_device->wwid; - } - } - - if (ioc->logging_level & MPT_DEBUG_TASK_SET_FULL) - starget_printk(KERN_INFO, sas_device->starget, "task set " - "full: handle(0x%04x), sas_addr(0x%016llx), depth(%d)\n", - handle, (unsigned long long)sas_address, current_depth); - - shost_for_each_device(sdev, ioc->shost) { - if (sdev->id == id && sdev->channel == channel) { - if (current_depth > sdev->queue_depth) { - if (ioc->logging_level & - MPT_DEBUG_TASK_SET_FULL) - sdev_printk(KERN_INFO, sdev, "strange " - "observation, the queue depth is" - " (%d) meanwhile fw queue depth " - "is (%d)\n", sdev->queue_depth, - current_depth); - continue; - } - depth = scsi_track_queue_full(sdev, - current_depth - 1); - if (depth > 0) - sdev_printk(KERN_INFO, sdev, "Queue depth " - "reduced to (%d)\n", depth); - else if (depth < 0) - sdev_printk(KERN_INFO, sdev, "Tagged Command " - "Queueing is being disabled\n"); - else if (depth == 0) - if (ioc->logging_level & - MPT_DEBUG_TASK_SET_FULL) - sdev_printk(KERN_INFO, sdev, - "Queue depth not changed yet\n"); - } - } -} - /** * _scsih_prep_device_scan - initialize parameters prior to device scan * @ioc: per adapter object @@ -6387,9 +6303,6 @@ _firmware_event_work(struct work_struct *work) case MPI2_EVENT_IR_OPERATION_STATUS: _scsih_sas_ir_operation_status_event(ioc, fw_event); break; - case MPI2_EVENT_TASK_SET_FULL: - _scsih_task_set_full(ioc, fw_event); - break; } _scsih_fw_event_free(ioc, fw_event); } @@ -6459,7 +6372,6 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, case MPI2_EVENT_SAS_DISCOVERY: case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: case MPI2_EVENT_IR_PHYSICAL_DISK: - case MPI2_EVENT_TASK_SET_FULL: break; default: /* ignore the rest */ -- cgit v1.2.3-59-g8ed1b From a93c6b45df57332b1703e0dc6f99a1bafc17f5e3 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Sat, 13 Nov 2010 04:39:11 +0530 Subject: [SCSI] mpt2sas: change queue depth with reason argument more appropriately change_queue_depth callback API changed The change_queue_depth callback changed where there is now an additional parameter called reason, with SCSI_QDEPTH_DEFAULT, SCSI_QDEPTH_QFULL, and SCSI_QDEPTH_RAMP_UP codes. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 37 +++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index e4987dbbaa50..608e8ce6cc74 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -1102,28 +1102,24 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc, } /** - * _scsih_change_queue_depth - setting device queue depth + * _scsih_adjust_queue_depth - setting device queue depth * @sdev: scsi device struct * @qdepth: requested queue depth - * @reason: calling context * - * Returns queue depth. + * + * Returns nothing */ -static int -_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) +static void +_scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth) { struct Scsi_Host *shost = sdev->host; int max_depth; - int tag_type; struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); struct MPT2SAS_DEVICE *sas_device_priv_data; struct MPT2SAS_TARGET *sas_target_priv_data; struct _sas_device *sas_device; unsigned long flags; - if (reason != SCSI_QDEPTH_DEFAULT) - return -EOPNOTSUPP; - max_depth = shost->can_queue; /* limit max device queue for SATA to 32 */ @@ -1149,8 +1145,27 @@ _scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) max_depth = 1; if (qdepth > max_depth) qdepth = max_depth; - tag_type = (qdepth == 1) ? 0 : MSG_SIMPLE_TAG; - scsi_adjust_queue_depth(sdev, tag_type, qdepth); + scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth); +} + +/** + * _scsih_change_queue_depth - setting device queue depth + * @sdev: scsi device struct + * @qdepth: requested queue depth + * @reason: SCSI_QDEPTH_DEFAULT/SCSI_QDEPTH_QFULL/SCSI_QDEPTH_RAMP_UP + * (see include/scsi/scsi_host.h for definition) + * + * Returns queue depth. + */ +static int +_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) +{ + if (reason == SCSI_QDEPTH_DEFAULT || reason == SCSI_QDEPTH_RAMP_UP) + _scsih_adjust_queue_depth(sdev, qdepth); + else if (reason == SCSI_QDEPTH_QFULL) + scsi_track_queue_full(sdev, qdepth); + else + return -EOPNOTSUPP; if (sdev->inquiry_len > 7) sdev_printk(KERN_INFO, sdev, "qdepth(%d), tagged(%d), " -- cgit v1.2.3-59-g8ed1b From b41c09d1afc2708b3fab395085f538e1fce9b571 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Sat, 13 Nov 2010 04:40:51 +0530 Subject: [SCSI] mpt2sas: Sanity check for phy count is added using max phy count Fix oops loading driver when there is direct attached SEP device The driver set max phys count to the value reported in sas iounit page zero. However this page doesn't take into account additional virutal phys. When sas topology event arrives, the phy count is larger than expected, and the driver accesses memory array beyond the end of allocated space, then oops. Manufacturing page 8 contains the info on direct attached phys. For this fix will making sure that sas topology event is not processing phys greater than the expected phy count. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 608e8ce6cc74..a68798350ec8 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -4796,7 +4796,7 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, int i; u16 parent_handle, handle; u16 reason_code; - u8 phy_number; + u8 phy_number, max_phys; struct _sas_node *sas_expander; struct _sas_device *sas_device; u64 sas_address; @@ -4834,11 +4834,13 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc, parent_handle); spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - if (sas_expander) + if (sas_expander) { sas_address = sas_expander->sas_address; - else if (parent_handle < ioc->sas_hba.num_phys) + max_phys = sas_expander->num_phys; + } else if (parent_handle < ioc->sas_hba.num_phys) { sas_address = ioc->sas_hba.sas_address; - else + max_phys = ioc->sas_hba.num_phys; + } else return; /* handle siblings events */ @@ -4852,6 +4854,8 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, ioc->pci_error_recovery) return; phy_number = event_data->StartPhyNum + i; + if (phy_number >= max_phys) + continue; reason_code = event_data->PHY[i].PhyStatus & MPI2_EVENT_SAS_TOPO_RC_MASK; if ((event_data->PHY[i].PhyStatus & -- cgit v1.2.3-59-g8ed1b From 37aaa78b8144d48d77bcd69a3353c88c0686df9e Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Sat, 13 Nov 2010 04:41:32 +0530 Subject: [SCSI] mpt2sas: Debug string changes from target to device. Changing debug print to correct string. Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index a68798350ec8..eda347c57979 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -2274,13 +2274,13 @@ _scsih_dev_reset(struct scsi_cmnd *scmd) struct scsi_target *starget = scmd->device->sdev_target; - starget_printk(KERN_INFO, starget, "attempting target reset! " + starget_printk(KERN_INFO, starget, "attempting device reset! " "scmd(%p)\n", scmd); _scsih_tm_display_info(ioc, scmd); sas_device_priv_data = scmd->device->hostdata; if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { - starget_printk(KERN_INFO, starget, "target been deleted! " + starget_printk(KERN_INFO, starget, "device been deleted! " "scmd(%p)\n", scmd); scmd->result = DID_NO_CONNECT << 16; scmd->scsi_done(scmd); -- cgit v1.2.3-59-g8ed1b From f0cebfb0177f26e214adca3511f37c089d1317f8 Mon Sep 17 00:00:00 2001 From: "Kashyap, Desai" Date: Sat, 13 Nov 2010 04:42:28 +0530 Subject: [SCSI] mpt2sas: Bump version 07.100.00.00 Signed-off-by: Kashyap Desai Signed-off-by: James Bottomley --- drivers/scsi/mpt2sas/mpt2sas_base.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index 428a8c2cf7e0..283568c6fb04 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -69,8 +69,8 @@ #define MPT2SAS_DRIVER_NAME "mpt2sas" #define MPT2SAS_AUTHOR "LSI Corporation " #define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver" -#define MPT2SAS_DRIVER_VERSION "06.100.00.00" -#define MPT2SAS_MAJOR_VERSION 06 +#define MPT2SAS_DRIVER_VERSION "07.100.00.00" +#define MPT2SAS_MAJOR_VERSION 07 #define MPT2SAS_MINOR_VERSION 100 #define MPT2SAS_BUILD_VERSION 00 #define MPT2SAS_RELEASE_VERSION 00 -- cgit v1.2.3-59-g8ed1b From 5ee32576269f33b66c6dbc98144aead1e74a1e91 Mon Sep 17 00:00:00 2001 From: Eddie Wai Date: Tue, 23 Nov 2010 15:29:20 -0800 Subject: [SCSI] bnx2i: Fixed bugs in the handling of unsolicited NOP-Ins Unsolicited NOP-Ins are placed in the receive queue of the hardware which requires to be read out regardless if the receive pipe is suspended or not. This patch adds the disposal of this RQ element under this condition. Also fixed the bug in the unsolicited NOP-In handling routine which checks for the RESERVED_ITT. Signed-off-by: Eddie Wai Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i_hwi.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index 8d9dbb33972f..16c76e0b2318 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c @@ -1549,11 +1549,9 @@ static int bnx2i_process_nopin_mesg(struct iscsi_session *session, struct iscsi_task *task; struct bnx2i_nop_in_msg *nop_in; struct iscsi_nopin *hdr; - u32 itt; int tgt_async_nop = 0; nop_in = (struct bnx2i_nop_in_msg *)cqe; - itt = nop_in->itt & ISCSI_NOP_IN_MSG_INDEX; spin_lock(&session->lock); hdr = (struct iscsi_nopin *)&bnx2i_conn->gen_pdu.resp_hdr; @@ -1563,7 +1561,7 @@ static int bnx2i_process_nopin_mesg(struct iscsi_session *session, hdr->exp_cmdsn = cpu_to_be32(nop_in->exp_cmd_sn); hdr->ttt = cpu_to_be32(nop_in->ttt); - if (itt == (u16) RESERVED_ITT) { + if (nop_in->itt == (u16) RESERVED_ITT) { bnx2i_unsol_pdu_adjust_rq(bnx2i_conn); hdr->itt = RESERVED_ITT; tgt_async_nop = 1; @@ -1571,7 +1569,8 @@ static int bnx2i_process_nopin_mesg(struct iscsi_session *session, } /* this is a response to one of our nop-outs */ - task = iscsi_itt_to_task(conn, itt); + task = iscsi_itt_to_task(conn, + (itt_t) (nop_in->itt & ISCSI_NOP_IN_MSG_INDEX)); if (task) { hdr->flags = ISCSI_FLAG_CMD_FINAL; hdr->itt = task->hdr->itt; @@ -1721,9 +1720,18 @@ static void bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn) if (nopin->cq_req_sn != qp->cqe_exp_seq_sn) break; - if (unlikely(test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx))) + if (unlikely(test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx))) { + if (nopin->op_code == ISCSI_OP_NOOP_IN && + nopin->itt == (u16) RESERVED_ITT) { + printk(KERN_ALERT "bnx2i: Unsolicited " + "NOP-In detected for suspended " + "connection dev=%s!\n", + bnx2i_conn->hba->netdev->name); + bnx2i_unsol_pdu_adjust_rq(bnx2i_conn); + goto cqe_out; + } break; - + } tgt_async_msg = 0; switch (nopin->op_code) { @@ -1770,10 +1778,9 @@ static void bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn) printk(KERN_ALERT "bnx2i: unknown opcode 0x%x\n", nopin->op_code); } - if (!tgt_async_msg) bnx2i_conn->ep->num_active_cmds--; - +cqe_out: /* clear out in production version only, till beta keep opcode * field intact, will be helpful in debugging (context dump) * nopin->op_code = 0; -- cgit v1.2.3-59-g8ed1b From 8eea2f55a65b9471276e78e5c86ddd19c4c0365c Mon Sep 17 00:00:00 2001 From: Eddie Wai Date: Tue, 23 Nov 2010 15:29:21 -0800 Subject: [SCSI] bnx2i: Added fix for NOP-Out response panic from unsolicited NOP-In The patch fixes the following situations where NOP-Out pkt is called for: - local unsolicited NOP-Out requests (requesting no NOP-In response) - local NOP-Out responses to unsolicited NOP-In requests kernel panic is observed due to double session spin_lock requests; one in the bnx2i_process_nopin_local_cmpl routine in bnx2i_hwi.c and the other in the iscsi_put_task routine in libiscsi.c The proposed fix is to export the currently static __iscsi_put_task() routine and have bnx2i call it directly instead of the iscsi_put_task() routine which holds the session spin lock. Signed-off-by: Eddie Wai Reviewed-by: Michael Chan Reviewed-by: Anil Veerabhadrappa Acked-by: Benjamin Li Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i_hwi.c | 2 +- drivers/scsi/libiscsi.c | 3 ++- include/scsi/libiscsi.h | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index 16c76e0b2318..32cf9306ffcb 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c @@ -1513,7 +1513,7 @@ static void bnx2i_process_nopin_local_cmpl(struct iscsi_session *session, task = iscsi_itt_to_task(conn, nop_in->itt & ISCSI_NOP_IN_MSG_INDEX); if (task) - iscsi_put_task(task); + __iscsi_put_task(task); spin_unlock(&session->lock); } diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index c15fde808c33..7551abe40900 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -539,11 +539,12 @@ void __iscsi_get_task(struct iscsi_task *task) } EXPORT_SYMBOL_GPL(__iscsi_get_task); -static void __iscsi_put_task(struct iscsi_task *task) +void __iscsi_put_task(struct iscsi_task *task) { if (atomic_dec_and_test(&task->refcount)) iscsi_free_task(task); } +EXPORT_SYMBOL_GPL(__iscsi_put_task); void iscsi_put_task(struct iscsi_task *task) { diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index b81d969ddc67..68e951d79f0b 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -419,6 +419,7 @@ extern struct iscsi_task *iscsi_itt_to_ctask(struct iscsi_conn *, itt_t); extern struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *, itt_t); extern void iscsi_requeue_task(struct iscsi_task *task); extern void iscsi_put_task(struct iscsi_task *task); +extern void __iscsi_put_task(struct iscsi_task *task); extern void __iscsi_get_task(struct iscsi_task *task); extern void iscsi_complete_scsi_task(struct iscsi_task *task, uint32_t exp_cmdsn, uint32_t max_cmdsn); -- cgit v1.2.3-59-g8ed1b From cf464fc5eb272f3f5964560ef2b8d632333afe0d Mon Sep 17 00:00:00 2001 From: Eddie Wai Date: Tue, 23 Nov 2010 15:29:22 -0800 Subject: [SCSI] bnx2i: Fixed the endian bug in the TMF LUN cmd send Added a be32_to_cpu call for the TMF LUN wqe. Signed-off-by: Eddie Wai Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i_hwi.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index 32cf9306ffcb..c9a3c0ff3c2f 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c @@ -385,6 +385,7 @@ int bnx2i_send_iscsi_tmf(struct bnx2i_conn *bnx2i_conn, struct bnx2i_cmd *bnx2i_cmd; struct bnx2i_tmf_request *tmfabort_wqe; u32 dword; + u32 scsi_lun[2]; bnx2i_cmd = (struct bnx2i_cmd *)mtask->dd_data; tmfabort_hdr = (struct iscsi_tm *)mtask->hdr; @@ -426,7 +427,10 @@ int bnx2i_send_iscsi_tmf(struct bnx2i_conn *bnx2i_conn, default: tmfabort_wqe->ref_itt = RESERVED_ITT; } - memcpy(tmfabort_wqe->lun, tmfabort_hdr->lun, sizeof(struct scsi_lun)); + memcpy(scsi_lun, tmfabort_hdr->lun, sizeof(struct scsi_lun)); + tmfabort_wqe->lun[0] = be32_to_cpu(scsi_lun[0]); + tmfabort_wqe->lun[1] = be32_to_cpu(scsi_lun[1]); + tmfabort_wqe->ref_cmd_sn = be32_to_cpu(tmfabort_hdr->refcmdsn); tmfabort_wqe->bd_list_addr_lo = (u32) bnx2i_conn->hba->mp_bd_dma; -- cgit v1.2.3-59-g8ed1b From 5bf3f39f9bda2750145a7da69ea9ae76d0054956 Mon Sep 17 00:00:00 2001 From: Eddie Wai Date: Tue, 23 Nov 2010 15:29:23 -0800 Subject: [SCSI] bnx2i: Fixed a cid leak issue for 5771X (10g) A cid leak issue was found when the connect destroy request exceeded the driver's disconnection timeout. This will lead to a cid resource leak issue. The fix is to allow the cid cleanup even when this happens. Signed-off-by: Eddie Wai Acked-by: Anil Veerabhadrappa Reviewed-by: Michael Chan Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i_iscsi.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index fb50efbce087..b7668122cf19 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -1640,18 +1640,26 @@ no_nx2_route: static int bnx2i_tear_down_conn(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep) { - if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) + if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic) && ep->cm_sk) hba->cnic->cm_destroy(ep->cm_sk); - if (test_bit(ADAPTER_STATE_GOING_DOWN, &ep->hba->adapter_state)) - ep->state = EP_STATE_DISCONN_COMPL; - if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type) && ep->state == EP_STATE_DISCONN_TIMEDOUT) { - printk(KERN_ALERT "bnx2i - ERROR - please submit GRC Dump," - " NW/PCIe trace, driver msgs to developers" - " for analysis\n"); - return 1; + if (ep->conn && ep->conn->cls_conn && + ep->conn->cls_conn->dd_data) { + struct iscsi_conn *conn = ep->conn->cls_conn->dd_data; + + /* Must suspend all rx queue activity for this ep */ + set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); + } + /* CONN_DISCONNECT timeout may or may not be an issue depending + * on what transcribed in TCP layer, different targets behave + * differently + */ + printk(KERN_ALERT "bnx2i (%s): - WARN - CONN_DISCON timed out, " + "please submit GRC Dump, NW/PCIe trace, " + "driver msgs to developers for analysis\n", + hba->netdev->name); } ep->state = EP_STATE_CLEANUP_START; -- cgit v1.2.3-59-g8ed1b From 94810e824df1509ad3ba401e57f74b922fd928c5 Mon Sep 17 00:00:00 2001 From: Eddie Wai Date: Tue, 23 Nov 2010 15:29:24 -0800 Subject: [SCSI] bnx2i: Fixed the remote TCP RST handling for the 570X (1g) Modified the handling of the remote TCP RST code so the chip can now flush the tx pipe accordingly upon a remote TCP RST reception. Signed-off-by: Eddie Wai Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i_hwi.c | 8 ++++++-- drivers/scsi/bnx2i/bnx2i_iscsi.c | 8 +++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index c9a3c0ff3c2f..0d40daefd572 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c @@ -2350,10 +2350,14 @@ static void bnx2i_cm_remote_close(struct cnic_sock *cm_sk) static void bnx2i_cm_remote_abort(struct cnic_sock *cm_sk) { struct bnx2i_endpoint *ep = (struct bnx2i_endpoint *) cm_sk->context; + u32 old_state = ep->state; ep->state = EP_STATE_TCP_RST_RCVD; - if (ep->conn) - bnx2i_recovery_que_add_conn(ep->hba, ep->conn); + if (old_state == EP_STATE_DISCONN_START) + wake_up_interruptible(&ep->ofld_wait); + else + if (ep->conn) + bnx2i_recovery_que_add_conn(ep->hba, ep->conn); } diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index b7668122cf19..4882b00b3539 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -1907,6 +1907,7 @@ static int bnx2i_ep_tcp_conn_active(struct bnx2i_endpoint *bnx2i_ep) switch (bnx2i_ep->state) { case EP_STATE_CONNECT_START: + case EP_STATE_CONNECT_FAILED: case EP_STATE_CLEANUP_FAILED: case EP_STATE_OFLD_FAILED: case EP_STATE_DISCONN_TIMEDOUT: @@ -1922,13 +1923,10 @@ static int bnx2i_ep_tcp_conn_active(struct bnx2i_endpoint *bnx2i_ep) ret = 1; break; case EP_STATE_TCP_RST_RCVD: - ret = 0; - break; - case EP_STATE_CONNECT_FAILED: if (cnic_dev_10g) - ret = 1; - else ret = 0; + else + ret = 1; break; default: ret = 0; -- cgit v1.2.3-59-g8ed1b From 252e44805bcfff5de2e05dd126f69a18e0b760f0 Mon Sep 17 00:00:00 2001 From: Eddie Wai Date: Tue, 23 Nov 2010 15:29:25 -0800 Subject: [SCSI] bnx2i: Allow to abort the connection if connect request times out In the situation where the connect completion response arrives after the connect request has already timed out, the connection was not being aborted but only the resource was being freed. This creates a problem for 5771X (10g) as the chip flags this with an assertion. This change will properly aborts the connection before freeing the resource. Signed-off-by: Eddie Wai Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i_iscsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index 4882b00b3539..a2c9b1f2ea5c 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -1906,13 +1906,13 @@ static int bnx2i_ep_tcp_conn_active(struct bnx2i_endpoint *bnx2i_ep) cnic_dev_10g = 1; switch (bnx2i_ep->state) { - case EP_STATE_CONNECT_START: case EP_STATE_CONNECT_FAILED: case EP_STATE_CLEANUP_FAILED: case EP_STATE_OFLD_FAILED: case EP_STATE_DISCONN_TIMEDOUT: ret = 0; break; + case EP_STATE_CONNECT_START: case EP_STATE_CONNECT_COMPL: case EP_STATE_ULP_UPDATE_START: case EP_STATE_ULP_UPDATE_COMPL: -- cgit v1.2.3-59-g8ed1b From 7a2962c77ced218faeeb7b5eda48abfebc578df2 Mon Sep 17 00:00:00 2001 From: Eddie Wai Date: Tue, 23 Nov 2010 15:29:26 -0800 Subject: [SCSI] bnx2i: Added mutex lock protection to conn_get_param Added net_dev mutex lock protection before accessing the csk parameters. Signed-off-by: Eddie Wai Reviewed-by: Benjamin Li Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i_iscsi.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index a2c9b1f2ea5c..07dd4f9036f0 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -1461,21 +1461,28 @@ static int bnx2i_conn_get_param(struct iscsi_cls_conn *cls_conn, struct bnx2i_conn *bnx2i_conn = conn->dd_data; int len = 0; + if (!(bnx2i_conn && bnx2i_conn->ep && bnx2i_conn->ep->hba)) + goto out; + switch (param) { case ISCSI_PARAM_CONN_PORT: - if (bnx2i_conn->ep) + mutex_lock(&bnx2i_conn->ep->hba->net_dev_lock); + if (bnx2i_conn->ep->cm_sk) len = sprintf(buf, "%hu\n", bnx2i_conn->ep->cm_sk->dst_port); + mutex_unlock(&bnx2i_conn->ep->hba->net_dev_lock); break; case ISCSI_PARAM_CONN_ADDRESS: - if (bnx2i_conn->ep) + mutex_lock(&bnx2i_conn->ep->hba->net_dev_lock); + if (bnx2i_conn->ep->cm_sk) len = sprintf(buf, "%pI4\n", &bnx2i_conn->ep->cm_sk->dst_ip); + mutex_unlock(&bnx2i_conn->ep->hba->net_dev_lock); break; default: return iscsi_conn_get_param(cls_conn, param, buf); } - +out: return len; } -- cgit v1.2.3-59-g8ed1b From 016ef69076f3e8f9e42f31152157f46812d25566 Mon Sep 17 00:00:00 2001 From: Eddie Wai Date: Tue, 23 Nov 2010 15:29:27 -0800 Subject: [SCSI] bnx2i: Removed the dynamic registration of CNIC The code no longer needs to dynamically register and unregister the CNIC device. The CNIC device will be kept registered until module unload. Signed-off-by: Eddie Wai Reviewed-by: Michael Chan Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i.h | 3 -- drivers/scsi/bnx2i/bnx2i_init.c | 82 ---------------------------------------- drivers/scsi/bnx2i/bnx2i_iscsi.c | 7 ---- 3 files changed, 92 deletions(-) diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h index a44b1b33fa18..2c34e22493d3 100644 --- a/drivers/scsi/bnx2i/bnx2i.h +++ b/drivers/scsi/bnx2i/bnx2i.h @@ -717,14 +717,11 @@ extern struct device_attribute *bnx2i_dev_attributes[]; * Function Prototypes */ extern void bnx2i_identify_device(struct bnx2i_hba *hba); -extern void bnx2i_register_device(struct bnx2i_hba *hba); extern void bnx2i_ulp_init(struct cnic_dev *dev); extern void bnx2i_ulp_exit(struct cnic_dev *dev); extern void bnx2i_start(void *handle); extern void bnx2i_stop(void *handle); -extern void bnx2i_reg_dev_all(void); -extern void bnx2i_unreg_dev_all(void); extern struct bnx2i_hba *get_adapter_list_head(void); struct bnx2i_conn *bnx2i_get_conn_from_id(struct bnx2i_hba *hba, diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c index 50c2aa3b8eb1..769311f6504d 100644 --- a/drivers/scsi/bnx2i/bnx2i_init.c +++ b/drivers/scsi/bnx2i/bnx2i_init.c @@ -65,8 +65,6 @@ MODULE_PARM_DESC(rq_size, "Configure RQ size"); u64 iscsi_error_mask = 0x00; -static void bnx2i_unreg_one_device(struct bnx2i_hba *hba) ; - /** * bnx2i_identify_device - identifies NetXtreme II device type @@ -238,86 +236,6 @@ void bnx2i_stop(void *handle) clear_bit(ADAPTER_STATE_UP, &hba->adapter_state); } -/** - * bnx2i_register_device - register bnx2i adapter instance with the cnic driver - * @hba: Adapter instance to register - * - * registers bnx2i adapter instance with the cnic driver while holding the - * adapter structure lock - */ -void bnx2i_register_device(struct bnx2i_hba *hba) -{ - int rc; - - if (test_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state) || - test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) { - return; - } - - rc = hba->cnic->register_device(hba->cnic, CNIC_ULP_ISCSI, hba); - - if (!rc) - set_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic); -} - - -/** - * bnx2i_reg_dev_all - registers all adapter instances with the cnic driver - * - * registers all bnx2i adapter instances with the cnic driver while holding - * the global resource lock - */ -void bnx2i_reg_dev_all(void) -{ - struct bnx2i_hba *hba, *temp; - - mutex_lock(&bnx2i_dev_lock); - list_for_each_entry_safe(hba, temp, &adapter_list, link) - bnx2i_register_device(hba); - mutex_unlock(&bnx2i_dev_lock); -} - - -/** - * bnx2i_unreg_one_device - unregister adapter instance with the cnic driver - * @hba: Adapter instance to unregister - * - * registers bnx2i adapter instance with the cnic driver while holding - * the adapter structure lock - */ -static void bnx2i_unreg_one_device(struct bnx2i_hba *hba) -{ - if (hba->ofld_conns_active || - !test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic) || - test_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state)) - return; - - hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI); - - /* ep_disconnect could come before NETDEV_DOWN, driver won't - * see NETDEV_DOWN as it already unregistered itself. - */ - hba->adapter_state = 0; - clear_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic); -} - -/** - * bnx2i_unreg_dev_all - unregisters all bnx2i instances with the cnic driver - * - * unregisters all bnx2i adapter instances with the cnic driver while holding - * the global resource lock - */ -void bnx2i_unreg_dev_all(void) -{ - struct bnx2i_hba *hba, *temp; - - mutex_lock(&bnx2i_dev_lock); - list_for_each_entry_safe(hba, temp, &adapter_list, link) - bnx2i_unreg_one_device(hba); - mutex_unlock(&bnx2i_dev_lock); -} - - /** * bnx2i_init_one - initialize an adapter instance and allocate memory resources * @hba: bnx2i adapter instance diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index 07dd4f9036f0..43b7dad8b48e 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -1606,8 +1606,6 @@ static struct bnx2i_hba *bnx2i_check_route(struct sockaddr *dst_addr) struct bnx2i_hba *hba; struct cnic_dev *cnic = NULL; - bnx2i_reg_dev_all(); - hba = get_adapter_list_head(); if (hba && hba->cnic) cnic = hba->cnic->cm_select_dev(desti, CNIC_ULP_ISCSI); @@ -1726,8 +1724,6 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost, if (shost) { /* driver is given scsi host to work with */ hba = iscsi_host_priv(shost); - /* Register the device with cnic if not already done so */ - bnx2i_register_device(hba); } else /* * check if the given destination can be reached through @@ -1853,7 +1849,6 @@ qp_resc_err: check_busy: mutex_unlock(&hba->net_dev_lock); nohba: - bnx2i_unreg_dev_all(); return ERR_PTR(rc); } @@ -2089,8 +2084,6 @@ return_bnx2i_ep: bnx2i_free_ep(ep); mutex_unlock(&hba->net_dev_lock); - if (!hba->ofld_conns_active) - bnx2i_unreg_dev_all(); wake_up_interruptible(&hba->eh_wait); } -- cgit v1.2.3-59-g8ed1b From 842158d7b7bc3b1a49c31f43ac20414234c33a8d Mon Sep 17 00:00:00 2001 From: Eddie Wai Date: Tue, 23 Nov 2010 15:29:28 -0800 Subject: [SCSI] bnx2i: Modified the bnx2i stop path to compensate for in progress ops The stop path has been augmented to wait a max of 10s for all in progress offload and destroy activities to complete before proceeding to terminate all active connections (via iscsid or forcefully). Note that any new offload and destroy requests are now blocked and return to the caller immediately. Signed-off-by: Eddie Wai Acked-by: Anil Veerabhadrappa Reviewed-by: Benjamin Li Reviewed-by: Michael Chan Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i_init.c | 21 +++++++++++++++++---- drivers/scsi/bnx2i/bnx2i_iscsi.c | 7 ++++++- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c index 769311f6504d..338caac418b8 100644 --- a/drivers/scsi/bnx2i/bnx2i_init.c +++ b/drivers/scsi/bnx2i/bnx2i_init.c @@ -209,13 +209,24 @@ void bnx2i_stop(void *handle) { struct bnx2i_hba *hba = handle; int conns_active; + int wait_delay = 1 * HZ; /* check if cleanup happened in GOING_DOWN context */ - if (!test_and_clear_bit(ADAPTER_STATE_GOING_DOWN, - &hba->adapter_state)) + if (!test_and_set_bit(ADAPTER_STATE_GOING_DOWN, + &hba->adapter_state)) { iscsi_host_for_each_session(hba->shost, bnx2i_drop_session); - + wait_delay = hba->hba_shutdown_tmo; + } + /* Wait for inflight offload connection tasks to complete before + * proceeding. Forcefully terminate all connection recovery in + * progress at the earliest, either in bind(), send_pdu(LOGIN), + * or conn_start() + */ + wait_event_interruptible_timeout(hba->eh_wait, + (list_empty(&hba->ep_ofld_list) && + list_empty(&hba->ep_destroy_list)), + 10 * HZ); /* Wait for all endpoints to be torn down, Chip will be reset once * control returns to network driver. So it is required to cleanup and * release all connection resources before returning from this routine. @@ -224,7 +235,7 @@ void bnx2i_stop(void *handle) conns_active = hba->ofld_conns_active; wait_event_interruptible_timeout(hba->eh_wait, (hba->ofld_conns_active != conns_active), - hba->hba_shutdown_tmo); + wait_delay); if (hba->ofld_conns_active == conns_active) break; } @@ -233,9 +244,11 @@ void bnx2i_stop(void *handle) /* This flag should be cleared last so that ep_disconnect() gracefully * cleans up connection context */ + clear_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state); clear_bit(ADAPTER_STATE_UP, &hba->adapter_state); } + /** * bnx2i_init_one - initialize an adapter instance and allocate memory resources * @hba: bnx2i adapter instance diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index 43b7dad8b48e..ac60c4c29e9a 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -1383,6 +1383,12 @@ static int bnx2i_conn_bind(struct iscsi_cls_session *cls_session, ep = iscsi_lookup_endpoint(transport_fd); if (!ep) return -EINVAL; + /* + * Forcefully terminate all in progress connection recovery at the + * earliest, either in bind(), send_pdu(LOGIN), or conn_start() + */ + if (bnx2i_adapter_ready(hba)) + return -EIO; bnx2i_ep = ep->dd_data; if ((bnx2i_ep->state == EP_STATE_TCP_FIN_RCVD) || @@ -1404,7 +1410,6 @@ static int bnx2i_conn_bind(struct iscsi_cls_session *cls_session, hba->netdev->name); return -EEXIST; } - bnx2i_ep->conn = bnx2i_conn; bnx2i_conn->ep = bnx2i_ep; bnx2i_conn->iscsi_conn_cid = bnx2i_ep->ep_iscsi_cid; -- cgit v1.2.3-59-g8ed1b From bee348770dcaeafa57bbd32129ce0cb16a4342d6 Mon Sep 17 00:00:00 2001 From: Eddie Wai Date: Tue, 23 Nov 2010 15:29:29 -0800 Subject: [SCSI] bnx2i: Added return code check for chip kwqe submission request Added the handling for cases when a chip request is made to the CNIC module but the hardware is not ready to accept. This would lead to many unnecessary wait timeouts. This code adds check in the connect establishment and destruction path. Signed-off-by: Eddie Wai Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i.h | 9 ++++--- drivers/scsi/bnx2i/bnx2i_hwi.c | 54 +++++++++++++++++++++++++++++----------- drivers/scsi/bnx2i/bnx2i_iscsi.c | 17 +++++++++++-- 3 files changed, 60 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h index 2c34e22493d3..866a22c4413d 100644 --- a/drivers/scsi/bnx2i/bnx2i.h +++ b/drivers/scsi/bnx2i/bnx2i.h @@ -649,6 +649,7 @@ enum { EP_STATE_OFLD_FAILED = 0x8000000, EP_STATE_CONNECT_FAILED = 0x10000000, EP_STATE_DISCONN_TIMEDOUT = 0x20000000, + EP_STATE_OFLD_FAILED_CID_BUSY = 0x80000000, }; /** @@ -758,11 +759,11 @@ extern int bnx2i_send_iscsi_logout(struct bnx2i_conn *conn, struct iscsi_task *mtask); extern void bnx2i_send_cmd_cleanup_req(struct bnx2i_hba *hba, struct bnx2i_cmd *cmd); -extern void bnx2i_send_conn_ofld_req(struct bnx2i_hba *hba, - struct bnx2i_endpoint *ep); -extern void bnx2i_update_iscsi_conn(struct iscsi_conn *conn); -extern void bnx2i_send_conn_destroy(struct bnx2i_hba *hba, +extern int bnx2i_send_conn_ofld_req(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep); +extern void bnx2i_update_iscsi_conn(struct iscsi_conn *conn); +extern int bnx2i_send_conn_destroy(struct bnx2i_hba *hba, + struct bnx2i_endpoint *ep); extern int bnx2i_alloc_qp_resc(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep); diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index 0d40daefd572..6d99040747d6 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c @@ -701,10 +701,11 @@ void bnx2i_send_cmd_cleanup_req(struct bnx2i_hba *hba, struct bnx2i_cmd *cmd) * this routine prepares and posts CONN_OFLD_REQ1/2 KWQE to initiate * iscsi connection context clean-up process */ -void bnx2i_send_conn_destroy(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep) +int bnx2i_send_conn_destroy(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep) { struct kwqe *kwqe_arr[2]; struct iscsi_kwqe_conn_destroy conn_cleanup; + int rc = -EINVAL; memset(&conn_cleanup, 0x00, sizeof(struct iscsi_kwqe_conn_destroy)); @@ -721,7 +722,9 @@ void bnx2i_send_conn_destroy(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep) kwqe_arr[0] = (struct kwqe *) &conn_cleanup; if (hba->cnic && hba->cnic->submit_kwqes) - hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, 1); + rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, 1); + + return rc; } @@ -732,8 +735,8 @@ void bnx2i_send_conn_destroy(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep) * * 5706/5708/5709 specific - prepares and posts CONN_OFLD_REQ1/2 KWQE */ -static void bnx2i_570x_send_conn_ofld_req(struct bnx2i_hba *hba, - struct bnx2i_endpoint *ep) +static int bnx2i_570x_send_conn_ofld_req(struct bnx2i_hba *hba, + struct bnx2i_endpoint *ep) { struct kwqe *kwqe_arr[2]; struct iscsi_kwqe_conn_offload1 ofld_req1; @@ -741,6 +744,7 @@ static void bnx2i_570x_send_conn_ofld_req(struct bnx2i_hba *hba, dma_addr_t dma_addr; int num_kwqes = 2; u32 *ptbl; + int rc = -EINVAL; ofld_req1.hdr.op_code = ISCSI_KWQE_OPCODE_OFFLOAD_CONN1; ofld_req1.hdr.flags = @@ -778,7 +782,9 @@ static void bnx2i_570x_send_conn_ofld_req(struct bnx2i_hba *hba, ofld_req2.num_additional_wqes = 0; if (hba->cnic && hba->cnic->submit_kwqes) - hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes); + rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes); + + return rc; } @@ -789,8 +795,8 @@ static void bnx2i_570x_send_conn_ofld_req(struct bnx2i_hba *hba, * * 57710 specific - prepares and posts CONN_OFLD_REQ1/2 KWQE */ -static void bnx2i_5771x_send_conn_ofld_req(struct bnx2i_hba *hba, - struct bnx2i_endpoint *ep) +static int bnx2i_5771x_send_conn_ofld_req(struct bnx2i_hba *hba, + struct bnx2i_endpoint *ep) { struct kwqe *kwqe_arr[5]; struct iscsi_kwqe_conn_offload1 ofld_req1; @@ -799,6 +805,7 @@ static void bnx2i_5771x_send_conn_ofld_req(struct bnx2i_hba *hba, dma_addr_t dma_addr; int num_kwqes = 2; u32 *ptbl; + int rc = -EINVAL; ofld_req1.hdr.op_code = ISCSI_KWQE_OPCODE_OFFLOAD_CONN1; ofld_req1.hdr.flags = @@ -844,7 +851,9 @@ static void bnx2i_5771x_send_conn_ofld_req(struct bnx2i_hba *hba, num_kwqes += 1; if (hba->cnic && hba->cnic->submit_kwqes) - hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes); + rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes); + + return rc; } /** @@ -855,12 +864,16 @@ static void bnx2i_5771x_send_conn_ofld_req(struct bnx2i_hba *hba, * * this routine prepares and posts CONN_OFLD_REQ1/2 KWQE */ -void bnx2i_send_conn_ofld_req(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep) +int bnx2i_send_conn_ofld_req(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep) { + int rc; + if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type)) - bnx2i_5771x_send_conn_ofld_req(hba, ep); + rc = bnx2i_5771x_send_conn_ofld_req(hba, ep); else - bnx2i_570x_send_conn_ofld_req(hba, ep); + rc = bnx2i_570x_send_conn_ofld_req(hba, ep); + + return rc; } @@ -2165,11 +2178,24 @@ static void bnx2i_process_ofld_cmpl(struct bnx2i_hba *hba, } if (ofld_kcqe->completion_status) { + ep->state = EP_STATE_OFLD_FAILED; if (ofld_kcqe->completion_status == ISCSI_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE) - printk(KERN_ALERT "bnx2i: unable to allocate" - " iSCSI context resources\n"); - ep->state = EP_STATE_OFLD_FAILED; + printk(KERN_ALERT "bnx2i (%s): ofld1 cmpl - unable " + "to allocate iSCSI context resources\n", + hba->netdev->name); + else if (ofld_kcqe->completion_status == + ISCSI_KCQE_COMPLETION_STATUS_INVALID_OPCODE) + printk(KERN_ALERT "bnx2i (%s): ofld1 cmpl - invalid " + "opcode\n", hba->netdev->name); + else if (ofld_kcqe->completion_status == + ISCSI_KCQE_COMPLETION_STATUS_CID_BUSY) + /* error status code valid only for 5771x chipset */ + ep->state = EP_STATE_OFLD_FAILED_CID_BUSY; + else + printk(KERN_ALERT "bnx2i (%s): ofld1 cmpl - invalid " + "error code %d\n", hba->netdev->name, + ofld_kcqe->completion_status); } else { ep->state = EP_STATE_OFLD_COMPL; cid_addr = ofld_kcqe->iscsi_conn_context_id; diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index ac60c4c29e9a..f622e89041cd 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -1682,7 +1682,9 @@ static int bnx2i_tear_down_conn(struct bnx2i_hba *hba, bnx2i_ep_destroy_list_add(hba, ep); /* destroy iSCSI context, wait for it to complete */ - bnx2i_send_conn_destroy(hba, ep); + if (bnx2i_send_conn_destroy(hba, ep)) + ep->state = EP_STATE_CLEANUP_CMPL; + wait_event_interruptible(ep->ofld_wait, (ep->state != EP_STATE_CLEANUP_START)); @@ -1781,7 +1783,18 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost, bnx2i_ep->ofld_timer.data = (unsigned long) bnx2i_ep; add_timer(&bnx2i_ep->ofld_timer); - bnx2i_send_conn_ofld_req(hba, bnx2i_ep); + if (bnx2i_send_conn_ofld_req(hba, bnx2i_ep)) { + if (bnx2i_ep->state == EP_STATE_OFLD_FAILED_CID_BUSY) { + printk(KERN_ALERT "bnx2i (%s): iscsi cid %d is busy\n", + hba->netdev->name, bnx2i_ep->ep_iscsi_cid); + rc = -EBUSY; + } else + rc = -ENOSPC; + printk(KERN_ALERT "bnx2i (%s): unable to send conn offld kwqe" + "\n", hba->netdev->name); + bnx2i_ep_ofld_list_del(hba, bnx2i_ep); + goto conn_failed; + } /* Wait for CNIC hardware to setup conn context and return 'cid' */ wait_event_interruptible(bnx2i_ep->ofld_wait, -- cgit v1.2.3-59-g8ed1b From a91031a6526441ff36552d53363037c3bbca0c5b Mon Sep 17 00:00:00 2001 From: Eddie Wai Date: Tue, 23 Nov 2010 15:29:30 -0800 Subject: [SCSI] bnx2i: Cleaned up various error conditions in ep_connect/disconnect Various error conditions inside ep_connect and ep_disconnect were either not being handled or not being handled correctly. This patch fixes all those issues. Signed-off-by: Eddie Wai Acked-by: Anil Veerabhadrappa Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i_iscsi.c | 67 ++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index f622e89041cd..24997c679f3c 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -411,7 +411,9 @@ static void bnx2i_free_ep(struct iscsi_endpoint *ep) bnx2i_ep->state = EP_STATE_IDLE; bnx2i_ep->hba->ofld_conns_active--; - bnx2i_free_iscsi_cid(bnx2i_ep->hba, bnx2i_ep->ep_iscsi_cid); + if (bnx2i_ep->ep_iscsi_cid != (u16) -1) + bnx2i_free_iscsi_cid(bnx2i_ep->hba, bnx2i_ep->ep_iscsi_cid); + if (bnx2i_ep->conn) { bnx2i_ep->conn->ep = NULL; bnx2i_ep->conn = NULL; @@ -1738,13 +1740,17 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost, */ hba = bnx2i_check_route(dst_addr); - if (!hba || test_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state)) { + if (!hba) { rc = -EINVAL; goto nohba; } + mutex_lock(&hba->net_dev_lock); + if (bnx2i_adapter_ready(hba) || !hba->cid_que.cid_free_cnt) { + rc = -EPERM; + goto check_busy; + } cnic = hba->cnic; - mutex_lock(&hba->net_dev_lock); ep = bnx2i_alloc_ep(hba); if (!ep) { rc = -ENOMEM; @@ -1752,23 +1758,21 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost, } bnx2i_ep = ep->dd_data; - if (bnx2i_adapter_ready(hba)) { - rc = -EPERM; - goto net_if_down; - } - bnx2i_ep->num_active_cmds = 0; iscsi_cid = bnx2i_alloc_iscsi_cid(hba); if (iscsi_cid == -1) { - printk(KERN_ALERT "alloc_ep: unable to allocate iscsi cid\n"); + printk(KERN_ALERT "bnx2i (%s): alloc_ep - unable to allocate " + "iscsi cid\n", hba->netdev->name); rc = -ENOMEM; - goto iscsi_cid_err; + bnx2i_free_ep(ep); + goto check_busy; } bnx2i_ep->hba_age = hba->age; rc = bnx2i_alloc_qp_resc(hba, bnx2i_ep); if (rc != 0) { - printk(KERN_ALERT "bnx2i: ep_conn, alloc QP resc error\n"); + printk(KERN_ALERT "bnx2i (%s): ep_conn - alloc QP resc error" + "\n", hba->netdev->name); rc = -ENOMEM; goto qp_resc_err; } @@ -1807,7 +1811,12 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost, bnx2i_ep_ofld_list_del(hba, bnx2i_ep); if (bnx2i_ep->state != EP_STATE_OFLD_COMPL) { - rc = -ENOSPC; + if (bnx2i_ep->state == EP_STATE_OFLD_FAILED_CID_BUSY) { + printk(KERN_ALERT "bnx2i (%s): iscsi cid %d is busy\n", + hba->netdev->name, bnx2i_ep->ep_iscsi_cid); + rc = -EBUSY; + } else + rc = -ENOSPC; goto conn_failed; } @@ -1815,7 +1824,8 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost, iscsi_cid, &bnx2i_ep->cm_sk, bnx2i_ep); if (rc) { rc = -EINVAL; - goto conn_failed; + /* Need to terminate and cleanup the connection */ + goto release_ep; } bnx2i_ep->cm_sk->rcv_buf = 256 * 1024; @@ -1859,8 +1869,6 @@ release_ep: return ERR_PTR(rc); } conn_failed: -net_if_down: -iscsi_cid_err: bnx2i_free_qp_resc(hba, bnx2i_ep); qp_resc_err: bnx2i_free_ep(ep); @@ -1979,7 +1987,8 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep) if (!cnic) return 0; - if (bnx2i_ep->state == EP_STATE_IDLE) + if (bnx2i_ep->state == EP_STATE_IDLE || + bnx2i_ep->state == EP_STATE_DISCONN_TIMEDOUT) return 0; if (!bnx2i_ep_tcp_conn_active(bnx2i_ep)) @@ -2005,9 +2014,10 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep) if (session->state == ISCSI_STATE_LOGGING_OUT) { if (bnx2i_ep->state == EP_STATE_LOGOUT_SENT) { /* Logout sent, but no resp */ - printk(KERN_ALERT "bnx2i - WARNING " - "logout response was not " - "received!\n"); + printk(KERN_ALERT "bnx2i (%s): WARNING" + " logout response was not " + "received!\n", + bnx2i_ep->hba->netdev->name); } else if (bnx2i_ep->state == EP_STATE_LOGOUT_RESP_RCVD) close = 1; @@ -2025,9 +2035,8 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep) else close_ret = cnic->cm_abort(bnx2i_ep->cm_sk); - /* No longer allow CFC delete if cm_close/abort fails the request */ if (close_ret) - printk(KERN_ALERT "bnx2i: %s close/abort(%d) returned %d\n", + printk(KERN_ALERT "bnx2i (%s): close/abort(%d) returned %d\n", bnx2i_ep->hba->netdev->name, close, close_ret); else /* wait for option-2 conn teardown */ @@ -2041,7 +2050,7 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep) destroy_conn: bnx2i_ep_active_list_del(hba, bnx2i_ep); if (bnx2i_tear_down_conn(hba, bnx2i_ep)) - ret = -EINVAL; + return -EINVAL; out: bnx2i_ep->state = EP_STATE_IDLE; return ret; @@ -2080,14 +2089,17 @@ static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep) mutex_lock(&hba->net_dev_lock); - if (bnx2i_ep->state == EP_STATE_IDLE) - goto return_bnx2i_ep; + if (bnx2i_ep->state == EP_STATE_DISCONN_TIMEDOUT) + goto out; - if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state)) + if (bnx2i_ep->state == EP_STATE_IDLE) goto free_resc; - if (bnx2i_ep->hba_age != hba->age) + if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state) || + (bnx2i_ep->hba_age != hba->age)) { + bnx2i_ep_active_list_del(hba, bnx2i_ep); goto free_resc; + } /* Do all chip cleanup here */ if (bnx2i_hw_ep_disconnect(bnx2i_ep)) { @@ -2096,11 +2108,12 @@ static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep) } free_resc: bnx2i_free_qp_resc(hba, bnx2i_ep); -return_bnx2i_ep: + if (bnx2i_conn) bnx2i_conn->ep = NULL; bnx2i_free_ep(ep); +out: mutex_unlock(&hba->net_dev_lock); wake_up_interruptible(&hba->eh_wait); -- cgit v1.2.3-59-g8ed1b From 11cec1e2e9d94bcda3446f52a868a2099a2eba4f Mon Sep 17 00:00:00 2001 From: Eddie Wai Date: Tue, 23 Nov 2010 15:29:31 -0800 Subject: [SCSI] bnx2i: Updated copyright and maintainer info Signed-off-by: Eddie Wai Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/57xx_iscsi_constants.h | 3 ++- drivers/scsi/bnx2i/57xx_iscsi_hsi.h | 3 ++- drivers/scsi/bnx2i/bnx2i.h | 3 ++- drivers/scsi/bnx2i/bnx2i_hwi.c | 3 ++- drivers/scsi/bnx2i/bnx2i_init.c | 3 ++- drivers/scsi/bnx2i/bnx2i_iscsi.c | 3 ++- drivers/scsi/bnx2i/bnx2i_sysfs.c | 3 ++- 7 files changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/bnx2i/57xx_iscsi_constants.h b/drivers/scsi/bnx2i/57xx_iscsi_constants.h index 1b6f86b2482d..30e6bdbd65af 100644 --- a/drivers/scsi/bnx2i/57xx_iscsi_constants.h +++ b/drivers/scsi/bnx2i/57xx_iscsi_constants.h @@ -1,12 +1,13 @@ /* 57xx_iscsi_constants.h: Broadcom NetXtreme II iSCSI HSI * - * Copyright (c) 2006 - 2009 Broadcom Corporation + * Copyright (c) 2006 - 2010 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Written by: Anil Veerabhadrappa (anilgv@broadcom.com) + * Maintained by: Eddie Wai (eddie.wai@broadcom.com) */ #ifndef __57XX_ISCSI_CONSTANTS_H_ #define __57XX_ISCSI_CONSTANTS_H_ diff --git a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h index 36af1afef9b6..dad6c8a34317 100644 --- a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h +++ b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h @@ -1,12 +1,13 @@ /* 57xx_iscsi_hsi.h: Broadcom NetXtreme II iSCSI HSI. * - * Copyright (c) 2006 - 2009 Broadcom Corporation + * Copyright (c) 2006 - 2010 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Written by: Anil Veerabhadrappa (anilgv@broadcom.com) + * Maintained by: Eddie Wai (eddie.wai@broadcom.com) */ #ifndef __57XX_ISCSI_HSI_LINUX_LE__ #define __57XX_ISCSI_HSI_LINUX_LE__ diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h index 866a22c4413d..e1ca5fe7e6bb 100644 --- a/drivers/scsi/bnx2i/bnx2i.h +++ b/drivers/scsi/bnx2i/bnx2i.h @@ -1,6 +1,6 @@ /* bnx2i.h: Broadcom NetXtreme II iSCSI driver. * - * Copyright (c) 2006 - 2009 Broadcom Corporation + * Copyright (c) 2006 - 2010 Broadcom Corporation * Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved. * Copyright (c) 2007, 2008 Mike Christie * @@ -9,6 +9,7 @@ * the Free Software Foundation. * * Written by: Anil Veerabhadrappa (anilgv@broadcom.com) + * Maintained by: Eddie Wai (eddie.wai@broadcom.com) */ #ifndef _BNX2I_H_ diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index 6d99040747d6..93753692c37a 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c @@ -1,6 +1,6 @@ /* bnx2i_hwi.c: Broadcom NetXtreme II iSCSI driver. * - * Copyright (c) 2006 - 2009 Broadcom Corporation + * Copyright (c) 2006 - 2010 Broadcom Corporation * Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved. * Copyright (c) 2007, 2008 Mike Christie * @@ -9,6 +9,7 @@ * the Free Software Foundation. * * Written by: Anil Veerabhadrappa (anilgv@broadcom.com) + * Maintained by: Eddie Wai (eddie.wai@broadcom.com) */ #include diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c index 338caac418b8..131ef80b95ff 100644 --- a/drivers/scsi/bnx2i/bnx2i_init.c +++ b/drivers/scsi/bnx2i/bnx2i_init.c @@ -1,6 +1,6 @@ /* bnx2i.c: Broadcom NetXtreme II iSCSI driver. * - * Copyright (c) 2006 - 2009 Broadcom Corporation + * Copyright (c) 2006 - 2010 Broadcom Corporation * Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved. * Copyright (c) 2007, 2008 Mike Christie * @@ -9,6 +9,7 @@ * the Free Software Foundation. * * Written by: Anil Veerabhadrappa (anilgv@broadcom.com) + * Maintained by: Eddie Wai (eddie.wai@broadcom.com) */ #include "bnx2i.h" diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index 24997c679f3c..f0dce26593eb 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -1,7 +1,7 @@ /* * bnx2i_iscsi.c: Broadcom NetXtreme II iSCSI driver. * - * Copyright (c) 2006 - 2009 Broadcom Corporation + * Copyright (c) 2006 - 2010 Broadcom Corporation * Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved. * Copyright (c) 2007, 2008 Mike Christie * @@ -10,6 +10,7 @@ * the Free Software Foundation. * * Written by: Anil Veerabhadrappa (anilgv@broadcom.com) + * Maintained by: Eddie Wai (eddie.wai@broadcom.com) */ #include diff --git a/drivers/scsi/bnx2i/bnx2i_sysfs.c b/drivers/scsi/bnx2i/bnx2i_sysfs.c index 96426b751eb2..9174196d9033 100644 --- a/drivers/scsi/bnx2i/bnx2i_sysfs.c +++ b/drivers/scsi/bnx2i/bnx2i_sysfs.c @@ -1,12 +1,13 @@ /* bnx2i_sysfs.c: Broadcom NetXtreme II iSCSI driver. * - * Copyright (c) 2004 - 2009 Broadcom Corporation + * Copyright (c) 2004 - 2010 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Written by: Anil Veerabhadrappa (anilgv@broadcom.com) + * Maintained by: Eddie Wai (eddie.wai@broadcom.com) */ #include "bnx2i.h" -- cgit v1.2.3-59-g8ed1b From 3db86353abba4549f665fbdde8572d619566afbb Mon Sep 17 00:00:00 2001 From: Eddie Wai Date: Tue, 23 Nov 2010 15:29:32 -0800 Subject: [SCSI] bnx2i: Updated version to 2.6.2.2 Signed-off-by: Eddie Wai Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/bnx2i_init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c index 131ef80b95ff..72a7b2d4a439 100644 --- a/drivers/scsi/bnx2i/bnx2i_init.c +++ b/drivers/scsi/bnx2i/bnx2i_init.c @@ -18,8 +18,8 @@ static struct list_head adapter_list = LIST_HEAD_INIT(adapter_list); static u32 adapter_count; #define DRV_MODULE_NAME "bnx2i" -#define DRV_MODULE_VERSION "2.1.3" -#define DRV_MODULE_RELDATE "Aug 10, 2010" +#define DRV_MODULE_VERSION "2.6.2.2" +#define DRV_MODULE_RELDATE "Nov 23, 2010" static char version[] __devinitdata = "Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \ -- cgit v1.2.3-59-g8ed1b From 52f94b6fd0d1ff9d935c52f8a6360834ed871d92 Mon Sep 17 00:00:00 2001 From: Maggie Date: Mon, 29 Nov 2010 18:21:32 -0800 Subject: [SCSI] bfa: fix regular sparse check warnings. Fix all sparse check warnings from make C=2. Signed-off-by: Maggie Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_fcs_lport.c | 6 +++--- drivers/scsi/bfa/bfa_fcs_rport.c | 8 -------- drivers/scsi/bfa/bfa_ioc.h | 2 +- drivers/scsi/bfa/bfa_ioc_cb.c | 2 +- drivers/scsi/bfa/bfa_ioc_ct.c | 2 +- drivers/scsi/bfa/bfad.c | 4 ++-- drivers/scsi/bfa/bfad_attr.c | 8 ++++---- drivers/scsi/bfa/bfad_debugfs.c | 42 +++++++++++++++++++++++++++++++++++----- drivers/scsi/bfa/bfad_drv.h | 6 +++--- 9 files changed, 52 insertions(+), 28 deletions(-) diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c index 8d651309302b..30665c744462 100644 --- a/drivers/scsi/bfa/bfa_fcs_lport.c +++ b/drivers/scsi/bfa/bfa_fcs_lport.c @@ -2103,7 +2103,7 @@ bfa_fcs_lport_fdmi_timeout(void *arg) bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT); } -void +static void bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi, struct bfa_fcs_fdmi_hba_attr_s *hba_attr) { @@ -2147,7 +2147,7 @@ bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi, hba_attr->max_ct_pyld = cpu_to_be32(FC_MAX_PDUSZ); } -void +static void bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi, struct bfa_fcs_fdmi_port_attr_s *port_attr) { @@ -4150,7 +4150,7 @@ bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port) bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY); } -void +static void bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port) { diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c index cf4a6e73e60d..60f2ddf23ebc 100644 --- a/drivers/scsi/bfa/bfa_fcs_rport.c +++ b/drivers/scsi/bfa/bfa_fcs_rport.c @@ -2359,14 +2359,6 @@ bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport) bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE); } -/* - * Called by fcptm to notify that the ITN cleanup is done. - */ -void -bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport) -{ - bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE); -} /* * brief diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index 9c407a87a1a1..eb1b005e5bc7 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h @@ -421,7 +421,7 @@ bfa_cb_image_get_chunk(int type, u32 off) return bfi_image_ct_cna_get_chunk(off); break; case BFI_IMAGE_CB_FC: return bfi_image_cb_fc_get_chunk(off); break; - default: return 0; + default: return NULL; } } diff --git a/drivers/scsi/bfa/bfa_ioc_cb.c b/drivers/scsi/bfa/bfa_ioc_cb.c index 909945043850..61f03cbe5431 100644 --- a/drivers/scsi/bfa/bfa_ioc_cb.c +++ b/drivers/scsi/bfa/bfa_ioc_cb.c @@ -32,7 +32,7 @@ static void bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix); static void bfa_ioc_cb_notify_hbfail(struct bfa_ioc_s *ioc); static void bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc); -struct bfa_ioc_hwif_s hwif_cb; +static struct bfa_ioc_hwif_s hwif_cb; /* * Called from bfa_ioc_attach() to map asic specific calls. diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c index 115730c0aa77..79fb31203636 100644 --- a/drivers/scsi/bfa/bfa_ioc_ct.c +++ b/drivers/scsi/bfa/bfa_ioc_ct.c @@ -32,7 +32,7 @@ static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix); static void bfa_ioc_ct_notify_hbfail(struct bfa_ioc_s *ioc); static void bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc); -struct bfa_ioc_hwif_s hwif_ct; +static struct bfa_ioc_hwif_s hwif_ct; /* * Called from bfa_ioc_attach() to map asic specific calls. diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index 6797720213b2..4239fdf0d2d1 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -61,12 +61,12 @@ int msix_disable_cb = 0, msix_disable_ct = 0; u32 bfi_image_ct_fc_size, bfi_image_ct_cna_size, bfi_image_cb_fc_size; u32 *bfi_image_ct_fc, *bfi_image_ct_cna, *bfi_image_cb_fc; -const char *msix_name_ct[] = { +static const char *msix_name_ct[] = { "cpe0", "cpe1", "cpe2", "cpe3", "rme0", "rme1", "rme2", "rme3", "ctrl" }; -const char *msix_name_cb[] = { +static const char *msix_name_cb[] = { "cpe0", "cpe1", "cpe2", "cpe3", "rme0", "rme1", "rme2", "rme3", "eemc", "elpu0", "elpu1", "epss", "mlpu" }; diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c index ed9fff440b5c..d727f055bd8a 100644 --- a/drivers/scsi/bfa/bfad_attr.c +++ b/drivers/scsi/bfa/bfad_attr.c @@ -25,7 +25,7 @@ /* * FC transport template entry, get SCSI target port ID. */ -void +static void bfad_im_get_starget_port_id(struct scsi_target *starget) { struct Scsi_Host *shost; @@ -51,7 +51,7 @@ bfad_im_get_starget_port_id(struct scsi_target *starget) /* * FC transport template entry, get SCSI target nwwn. */ -void +static void bfad_im_get_starget_node_name(struct scsi_target *starget) { struct Scsi_Host *shost; @@ -77,7 +77,7 @@ bfad_im_get_starget_node_name(struct scsi_target *starget) /* * FC transport template entry, get SCSI target pwwn. */ -void +static void bfad_im_get_starget_port_name(struct scsi_target *starget) { struct Scsi_Host *shost; @@ -103,7 +103,7 @@ bfad_im_get_starget_port_name(struct scsi_target *starget) /* * FC transport template entry, get SCSI host port ID. */ -void +static void bfad_im_get_host_port_id(struct Scsi_Host *shost) { struct bfad_im_port_s *im_port = diff --git a/drivers/scsi/bfa/bfad_debugfs.c b/drivers/scsi/bfa/bfad_debugfs.c index 1fedeeb4ac1f..0fbd620474c7 100644 --- a/drivers/scsi/bfa/bfad_debugfs.c +++ b/drivers/scsi/bfa/bfad_debugfs.c @@ -208,7 +208,7 @@ bfad_debugfs_read(struct file *file, char __user *buf, if (!debug || !debug->debug_buffer) return 0; - return memory_read_from_buffer(buf, nbytes, pos, + return simple_read_from_buffer(buf, nbytes, pos, debug->debug_buffer, debug->buffer_len); } @@ -254,7 +254,7 @@ bfad_debugfs_read_regrd(struct file *file, char __user *buf, if (!bfad->regdata) return 0; - rc = memory_read_from_buffer(buf, nbytes, pos, + rc = simple_read_from_buffer(buf, nbytes, pos, bfad->regdata, bfad->reglen); if ((*pos + nbytes) >= bfad->reglen) { @@ -279,15 +279,31 @@ bfad_debugfs_write_regrd(struct file *file, const char __user *buf, u32 *regbuf; void __iomem *rb, *reg_addr; unsigned long flags; + void *kern_buf; - rc = sscanf(buf, "%x:%x", &addr, &len); + kern_buf = kzalloc(nbytes, GFP_KERNEL); + + if (!kern_buf) { + printk(KERN_INFO "bfad[%d]: Failed to allocate buffer\n", + bfad->inst_no); + return -ENOMEM; + } + + if (copy_from_user(kern_buf, (void __user *)buf, nbytes)) { + kfree(kern_buf); + return -ENOMEM; + } + + rc = sscanf(kern_buf, "%x:%x", &addr, &len); if (rc < 2) { printk(KERN_INFO "bfad[%d]: %s failed to read user buf\n", bfad->inst_no, __func__); + kfree(kern_buf); return -EINVAL; } + kfree(kern_buf); kfree(bfad->regdata); bfad->regdata = NULL; bfad->reglen = 0; @@ -339,14 +355,30 @@ bfad_debugfs_write_regwr(struct file *file, const char __user *buf, int addr, val, rc; void __iomem *reg_addr; unsigned long flags; + void *kern_buf; + + kern_buf = kzalloc(nbytes, GFP_KERNEL); + + if (!kern_buf) { + printk(KERN_INFO "bfad[%d]: Failed to allocate buffer\n", + bfad->inst_no); + return -ENOMEM; + } + + if (copy_from_user(kern_buf, (void __user *)buf, nbytes)) { + kfree(kern_buf); + return -ENOMEM; + } - rc = sscanf(buf, "%x:%x", &addr, &val); + rc = sscanf(kern_buf, "%x:%x", &addr, &val); if (rc < 2) { printk(KERN_INFO "bfad[%d]: %s failed to read user buf\n", bfad->inst_no, __func__); + kfree(kern_buf); return -EINVAL; } + kfree(kern_buf); addr &= BFA_REG_ADDRMSK(bfa); /* offset only 17 bit and word align */ @@ -359,7 +391,7 @@ bfad_debugfs_write_regwr(struct file *file, const char __user *buf, return -EINVAL; } - reg_addr = (u32 *) ((u8 *) bfa_ioc_bar0(ioc) + addr); + reg_addr = (bfa_ioc_bar0(ioc)) + addr; spin_lock_irqsave(&bfad->bfad_lock, flags); writel(val, reg_addr); spin_unlock_irqrestore(&bfad->bfad_lock, flags); diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h index d5ce2349ac59..b9bcb0b99b8a 100644 --- a/drivers/scsi/bfa/bfad_drv.h +++ b/drivers/scsi/bfa/bfad_drv.h @@ -263,10 +263,10 @@ struct bfad_hal_comp { */ #define nextLowerInt(x) \ do { \ - int i; \ + int __i; \ (*x)--; \ - for (i = 1; i < (sizeof(int)*8); i <<= 1) \ - (*x) = (*x) | (*x) >> i; \ + for (__i = 1; __i < (sizeof(int)*8); __i <<= 1) \ + (*x) = (*x) | (*x) >> __i; \ (*x)++; \ (*x) = (*x) >> 1; \ } while (0) -- cgit v1.2.3-59-g8ed1b From 50444a340028119ce5ba45d60b4cf44e3e6e1b32 Mon Sep 17 00:00:00 2001 From: Maggie Date: Mon, 29 Nov 2010 18:26:32 -0800 Subject: [SCSI] bfa: fix endianess sparse check warnings First round of fix for the endianess check warnings from make C=2 CF="-D__CHECK_ENDIAN__". Signed-off-by: Maggie Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_cb_ioim.h | 2 +- drivers/scsi/bfa/bfa_defs_svc.h | 8 +- drivers/scsi/bfa/bfa_fc.h | 56 +++++----- drivers/scsi/bfa/bfa_fcbuild.c | 44 ++++---- drivers/scsi/bfa/bfa_fcbuild.h | 28 ++--- drivers/scsi/bfa/bfa_fcs.h | 14 +-- drivers/scsi/bfa/bfa_fcs_lport.c | 226 ++++++++++++++++++++------------------- drivers/scsi/bfa/bfa_fcs_rport.c | 2 +- drivers/scsi/bfa/bfa_ioc.c | 5 +- drivers/scsi/bfa/bfa_ioc.h | 8 +- drivers/scsi/bfa/bfa_port.c | 2 +- drivers/scsi/bfa/bfa_svc.c | 4 +- drivers/scsi/bfa/bfi.h | 4 +- drivers/scsi/bfa/bfi_ms.h | 50 ++++----- 14 files changed, 228 insertions(+), 225 deletions(-) diff --git a/drivers/scsi/bfa/bfa_cb_ioim.h b/drivers/scsi/bfa/bfa_cb_ioim.h index 6f021015f1f6..afb573878e20 100644 --- a/drivers/scsi/bfa/bfa_cb_ioim.h +++ b/drivers/scsi/bfa/bfa_cb_ioim.h @@ -32,7 +32,7 @@ static inline lun_t bfad_int_to_lun(u32 luno) { union { - u16 scsi_lun[4]; + __be16 scsi_lun[4]; lun_t bfa_lun; } lun; diff --git a/drivers/scsi/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h index e24e9f7ca81f..648c84176722 100644 --- a/drivers/scsi/bfa/bfa_defs_svc.h +++ b/drivers/scsi/bfa/bfa_defs_svc.h @@ -34,8 +34,8 @@ struct bfa_iocfc_intr_attr_s { u8 coalesce; /* enable/disable coalescing */ u8 rsvd[3]; - u16 latency; /* latency in microseconds */ - u16 delay; /* delay in microseconds */ + __be16 latency; /* latency in microseconds */ + __be16 delay; /* delay in microseconds */ }; /* @@ -743,7 +743,7 @@ struct bfa_port_cfg_s { u8 qos_enabled; /* qos enabled or not */ u8 cfg_hardalpa; /* is hard alpa configured */ u8 hardalpa; /* configured hard alpa */ - u16 maxfrsize; /* maximum frame size */ + __be16 maxfrsize; /* maximum frame size */ u8 rx_bbcredit; /* receive buffer credits */ u8 tx_bbcredit; /* transmit buffer credits */ u8 ratelimit; /* ratelimit enabled or not */ @@ -843,7 +843,7 @@ struct bfa_fcport_fcf_s { u8 fka_disabled; /* FKA is disabled */ u8 maxsz_verified; /* FCoE max size verified */ u8 fc_map[3]; /* FC map */ - u16 vlan; /* FCoE vlan tag/priority */ + __be16 vlan; /* FCoE vlan tag/priority */ u32 fka_adv_per; /* FIP ka advert. period */ mac_t mac; /* FCF mac */ }; diff --git a/drivers/scsi/bfa/bfa_fc.h b/drivers/scsi/bfa/bfa_fc.h index e929d25b09e3..ce5274a017fa 100644 --- a/drivers/scsi/bfa/bfa_fc.h +++ b/drivers/scsi/bfa/bfa_fc.h @@ -82,7 +82,7 @@ struct fchs_s { u8 df_ctl; /* data field control */ u16 seq_cnt; /* sequence count */ - u16 ox_id; /* originator exchange ID */ + __be16 ox_id; /* originator exchange ID */ u16 rx_id; /* responder exchange ID */ u32 ro; /* relative offset */ @@ -316,7 +316,7 @@ enum { struct fc_plogi_csp_s { u8 verhi; /* FC-PH high version */ u8 verlo; /* FC-PH low version */ - u16 bbcred; /* BB_Credit */ + __be16 bbcred; /* BB_Credit */ #ifdef __BIGENDIAN u8 ciro:1, /* continuously increasing RO */ @@ -355,12 +355,12 @@ struct fc_plogi_csp_s { hg_supp:1; #endif - u16 rxsz; /* recieve data_field size */ + __be16 rxsz; /* recieve data_field size */ - u16 conseq; - u16 ro_bitmap; + __be16 conseq; + __be16 ro_bitmap; - u32 e_d_tov; + __be32 e_d_tov; }; /* @@ -873,7 +873,7 @@ struct fc_rscn_event_s { struct fc_rscn_pl_s { u8 command; u8 pagelen; - u16 payldlen; + __be16 payldlen; struct fc_rscn_event_s event[1]; }; @@ -926,9 +926,9 @@ struct fc_rnid_common_id_data_s { struct fc_rnid_general_topology_data_s { u32 vendor_unique[4]; - u32 asso_type; + __be32 asso_type; u32 phy_port_num; - u32 num_attached_nodes; + __be32 num_attached_nodes; u32 node_mgmt:8; u32 ip_version:8; u32 udp_tcp_port_num:16; @@ -984,8 +984,8 @@ enum fc_rpsc_op_speed { }; struct fc_rpsc_speed_info_s { - u16 port_speed_cap; /*! see enum fc_rpsc_speed_cap */ - u16 port_op_speed; /*! see enum fc_rpsc_op_speed */ + __be16 port_speed_cap; /*! see enum fc_rpsc_speed_cap */ + __be16 port_op_speed; /*! see enum fc_rpsc_op_speed */ }; enum link_e2e_beacon_subcmd { @@ -1056,9 +1056,9 @@ struct fc_rpsc_acc_s { struct fc_rpsc2_cmd_s { struct fc_els_cmd_s els_cmd; - u32 token; + __be32 token; u16 resvd; - u16 num_pids; /* Number of pids in the request */ + __be16 num_pids; /* Number of pids in the request */ struct { u32 rsvd1:8; u32 pid:24; /* port identifier */ @@ -1076,12 +1076,12 @@ enum fc_rpsc2_port_type { * RPSC2 portInfo entry structure */ struct fc_rpsc2_port_info_s { - u32 pid; /* PID */ - u16 resvd1; - u16 index; /* port number / index */ - u8 resvd2; - u8 type; /* port type N/NL/... */ - u16 speed; /* port Operating Speed */ + __be32 pid; /* PID */ + u16 resvd1; + __be16 index; /* port number / index */ + u8 resvd2; + u8 type; /* port type N/NL/... */ + __be16 speed; /* port Operating Speed */ }; /* @@ -1090,7 +1090,7 @@ struct fc_rpsc2_port_info_s { struct fc_rpsc2_acc_s { u8 els_cmd; u8 resvd; - u16 num_pids; /* Number of pids in the request */ + __be16 num_pids; /* Number of pids in the request */ struct fc_rpsc2_port_info_s port_info[1]; /* port information */ }; @@ -1200,7 +1200,7 @@ struct fcp_cmnd_s { /* * !!! additional cdb bytes follows here!!! */ - u32 fcp_dl; /* bytes to be transferred */ + __be32 fcp_dl; /* bytes to be transferred */ }; #define fcp_cmnd_cdb_len(_cmnd) ((_cmnd)->addl_cdb_len * 4 + FCP_CMND_CDB_LEN) @@ -1469,7 +1469,7 @@ struct fcgs_gidpn_resp_s { struct fcgs_rftid_req_s { u32 rsvd:8; u32 dap:24; /* port identifier */ - u32 fc4_type[8]; /* fc4 types */ + __be32 fc4_type[8]; /* fc4 types */ }; /* @@ -1764,7 +1764,7 @@ struct fcgs_req_s { /* Accept Response to GMAL */ struct fcgs_gmal_resp_s { - u32 ms_len; /* Num of entries */ + __be32 ms_len; /* Num of entries */ u8 ms_ma[256]; }; @@ -1856,8 +1856,8 @@ enum fdmi_port_attribute_type { * FDMI attribute */ struct fdmi_attr_s { - u16 type; - u16 len; + __be16 type; + __be16 len; u8 value[1]; }; @@ -1865,7 +1865,7 @@ struct fdmi_attr_s { * HBA Attribute Block */ struct fdmi_hba_attr_s { - u32 attr_count; /* # of attributes */ + __be32 attr_count; /* # of attributes */ struct fdmi_attr_s hba_attr; /* n attributes */ }; @@ -1873,7 +1873,7 @@ struct fdmi_hba_attr_s { * Registered Port List */ struct fdmi_port_list_s { - u32 num_ports; /* number Of Port Entries */ + __be32 num_ports; /* number Of Port Entries */ wwn_t port_entry; /* one or more */ }; @@ -1881,7 +1881,7 @@ struct fdmi_port_list_s { * Port Attribute Block */ struct fdmi_port_attr_s { - u32 attr_count; /* # of attributes */ + __be32 attr_count; /* # of attributes */ struct fdmi_attr_s port_attr; /* n attributes */ }; diff --git a/drivers/scsi/bfa/bfa_fcbuild.c b/drivers/scsi/bfa/bfa_fcbuild.c index 9c725314b513..322b11e10d67 100644 --- a/drivers/scsi/bfa/bfa_fcbuild.c +++ b/drivers/scsi/bfa/bfa_fcbuild.c @@ -25,9 +25,9 @@ * static build functions */ static void fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, - u16 ox_id); + __be16 ox_id); static void fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, - u16 ox_id); + __be16 ox_id); static struct fchs_s fc_els_req_tmpl; static struct fchs_s fc_els_rsp_tmpl; static struct fchs_s fc_bls_req_tmpl; @@ -157,7 +157,7 @@ fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u32 ox_id) } void -fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id) +fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id) { memcpy(fchs, &fc_els_req_tmpl, sizeof(struct fchs_s)); fchs->d_id = (d_id); @@ -166,7 +166,7 @@ fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id) } static void -fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id) +fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id) { memcpy(fchs, &fc_els_rsp_tmpl, sizeof(struct fchs_s)); fchs->d_id = d_id; @@ -196,7 +196,7 @@ fc_els_rsp_parse(struct fchs_s *fchs, int len) } static void -fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id) +fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id) { memcpy(fchs, &fc_bls_rsp_tmpl, sizeof(struct fchs_s)); fchs->d_id = d_id; @@ -206,7 +206,7 @@ fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id) static u16 fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, - u16 ox_id, wwn_t port_name, wwn_t node_name, + __be16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size, u8 els_code) { struct fc_logi_s *plogi = (struct fc_logi_s *) (pld); @@ -233,7 +233,7 @@ fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id, u8 set_npiv, u8 set_auth, u16 local_bb_credits) { u32 d_id = bfa_os_hton3b(FC_FABRIC_PORT); - u32 *vvl_info; + __be32 *vvl_info; memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s)); @@ -267,7 +267,7 @@ fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id, u16 fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id, - u16 ox_id, wwn_t port_name, wwn_t node_name, + __be16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size, u16 local_bb_credits) { u32 d_id = 0; @@ -392,7 +392,7 @@ fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, u16 fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, - u16 ox_id, enum bfa_lport_role role) + __be16 ox_id, enum bfa_lport_role role) { struct fc_prli_s *prli = (struct fc_prli_s *) (pld); @@ -458,7 +458,7 @@ fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id, u32 s_id, static u16 fc_adisc_x_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id, - u32 s_id, u16 ox_id, wwn_t port_name, + u32 s_id, __be16 ox_id, wwn_t port_name, wwn_t node_name, u8 els_code) { memset(adisc, '\0', sizeof(struct fc_adisc_s)); @@ -480,7 +480,7 @@ fc_adisc_x_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id, u16 fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id, - u32 s_id, u16 ox_id, wwn_t port_name, wwn_t node_name) + u32 s_id, __be16 ox_id, wwn_t port_name, wwn_t node_name) { return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name, node_name, FC_ELS_ADISC); @@ -488,7 +488,7 @@ fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id, u16 fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id, - u32 s_id, u16 ox_id, wwn_t port_name, + u32 s_id, __be16 ox_id, wwn_t port_name, wwn_t node_name) { return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name, @@ -592,7 +592,7 @@ fc_rrq_build(struct fchs_s *fchs, struct fc_rrq_s *rrq, u32 d_id, u32 s_id, u16 fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, - u16 ox_id) + __be16 ox_id) { struct fc_els_cmd_s *acc = pld; @@ -606,7 +606,7 @@ fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, u16 fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt, u32 d_id, - u32 s_id, u16 ox_id, u8 reason_code, + u32 s_id, __be16 ox_id, u8 reason_code, u8 reason_code_expl) { fc_els_rsp_build(fchs, d_id, s_id, ox_id); @@ -622,7 +622,7 @@ fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt, u32 d_id, u16 fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id, - u32 s_id, u16 ox_id, u16 rx_id) + u32 s_id, __be16 ox_id, u16 rx_id) { fc_bls_rsp_build(fchs, d_id, s_id, ox_id); @@ -638,7 +638,7 @@ fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id, u16 fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd, u32 d_id, - u32 s_id, u16 ox_id) + u32 s_id, __be16 ox_id) { fc_els_rsp_build(fchs, d_id, s_id, ox_id); memset(els_cmd, 0, sizeof(struct fc_els_cmd_s)); @@ -666,7 +666,7 @@ fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code) u16 fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc, - u32 d_id, u32 s_id, u16 ox_id, int num_pages) + u32 d_id, u32 s_id, __be16 ox_id, int num_pages) { int page; @@ -690,7 +690,7 @@ fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc, u16 fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc, u32 d_id, - u32 s_id, u16 ox_id, int num_pages) + u32 s_id, __be16 ox_id, int num_pages) { int page; @@ -728,7 +728,7 @@ fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid, u32 d_id, u16 fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc, u32 d_id, - u32 s_id, u16 ox_id, u32 data_format, + u32 s_id, __be16 ox_id, u32 data_format, struct fc_rnid_common_id_data_s *common_id_data, struct fc_rnid_general_topology_data_s *gen_topo_data) { @@ -788,7 +788,7 @@ fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2, u32 d_id, u16 fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc, - u32 d_id, u32 s_id, u16 ox_id, + u32 d_id, u32 s_id, __be16 ox_id, struct fc_rpsc_speed_info_s *oper_speed) { memset(rpsc_acc, 0, sizeof(struct fc_rpsc_acc_s)); @@ -995,7 +995,7 @@ fc_rrq_rsp_parse(struct fchs_s *fchs, int len) } u16 -fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id, +fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id, u32 reason_code, u32 reason_expl) { struct fc_ba_rjt_s *ba_rjt = (struct fc_ba_rjt_s *) (fchs + 1); @@ -1356,7 +1356,7 @@ void fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask) { u8 index; - u32 *ptr = (u32 *) bit_mask; + __be32 *ptr = (__be32 *) bit_mask; u32 type_value; /* diff --git a/drivers/scsi/bfa/bfa_fcbuild.h b/drivers/scsi/bfa/bfa_fcbuild.h index 73abd02e53cc..1737e08e1c01 100644 --- a/drivers/scsi/bfa/bfa_fcbuild.h +++ b/drivers/scsi/bfa/bfa_fcbuild.h @@ -138,7 +138,7 @@ u16 fc_fdisc_build(struct fchs_s *buf, struct fc_logi_s *flogi, u32 s_id, u16 pdu_size); u16 fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, - u32 s_id, u16 ox_id, + u32 s_id, __be16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size, u16 local_bb_credits); @@ -186,7 +186,7 @@ u16 fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u16 pdu_size); u16 fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, - u32 d_id, u32 s_id, u16 ox_id, wwn_t port_name, + u32 d_id, u32 s_id, __be16 ox_id, wwn_t port_name, wwn_t node_name); enum fc_parse_status fc_adisc_parse(struct fchs_s *fchs, void *pld, @@ -196,20 +196,20 @@ enum fc_parse_status fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len, wwn_t port_name, wwn_t node_name); u16 fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, - u32 d_id, u32 s_id, u16 ox_id, + u32 d_id, u32 s_id, __be16 ox_id, wwn_t port_name, wwn_t node_name); u16 fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt, - u32 d_id, u32 s_id, u16 ox_id, + u32 d_id, u32 s_id, __be16 ox_id, u8 reason_code, u8 reason_code_expl); u16 fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd, - u32 d_id, u32 s_id, u16 ox_id); + u32 d_id, u32 s_id, __be16 ox_id); u16 fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, u16 ox_id); enum fc_parse_status fc_prli_rsp_parse(struct fc_prli_s *prli, int len); u16 fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, - u32 s_id, u16 ox_id, + u32 s_id, __be16 ox_id, enum bfa_lport_role role); u16 fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid, @@ -218,7 +218,7 @@ u16 fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid, u16 fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc, u32 d_id, u32 s_id, - u16 ox_id, u32 data_format, + __be16 ox_id, u32 data_format, struct fc_rnid_common_id_data_s *common_id_data, struct fc_rnid_general_topology_data_s *gen_topo_data); @@ -228,7 +228,7 @@ u16 fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc, u32 d_id, u32 s_id, u16 ox_id); u16 fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc, u32 d_id, u32 s_id, - u16 ox_id, struct fc_rpsc_speed_info_s *oper_speed); + __be16 ox_id, struct fc_rpsc_speed_info_s *oper_speed); u16 fc_gid_ft_build(struct fchs_s *fchs, void *pld, u32 s_id, u8 fc4_type); @@ -251,7 +251,7 @@ u16 fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id, u32 s_id, u16 ox_id, wwn_t port_name); u16 fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, - u32 s_id, u16 ox_id); + u32 s_id, __be16 ox_id); u16 fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 cmd_code); @@ -261,7 +261,7 @@ u16 fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn); void fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask); void fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, - u16 ox_id); + __be16 ox_id); enum fc_parse_status fc_els_rsp_parse(struct fchs_s *fchs, int len); @@ -274,15 +274,15 @@ enum fc_parse_status fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name, wwn_t port_name); u16 fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id, - u32 s_id, u16 ox_id, u16 rx_id); + u32 s_id, __be16 ox_id, u16 rx_id); int fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code); u16 fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc, - u32 d_id, u32 s_id, u16 ox_id, int num_pages); + u32 d_id, u32 s_id, __be16 ox_id, int num_pages); u16 fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc, - u32 d_id, u32 s_id, u16 ox_id, int num_pages); + u32 d_id, u32 s_id, __be16 ox_id, int num_pages); u16 fc_logo_rsp_parse(struct fchs_s *fchs, int len); @@ -304,7 +304,7 @@ u16 fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 fc_tprlo_rsp_parse(struct fchs_s *fchs, int len); u16 fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id, - u16 ox_id, u32 reason_code, u32 reason_expl); + __be16 ox_id, u32 reason_code, u32 reason_expl); u16 fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, u32 port_id); diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h index 9cb6a55977c3..5a8b928f8db3 100644 --- a/drivers/scsi/bfa/bfa_fcs.h +++ b/drivers/scsi/bfa/bfa_fcs.h @@ -109,7 +109,7 @@ struct bfa_fcs_lport_loop_s { struct bfa_fcs_lport_n2n_s { u32 rsvd; - u16 reply_oxid; /* ox_id from the req flogi to be + __be16 reply_oxid; /* ox_id from the req flogi to be *used in flogi acc */ wwn_t rem_port_wwn; /* Attached port's wwn */ }; @@ -406,7 +406,7 @@ struct bfa_fcs_rport_s { struct bfad_rport_s *rp_drv; /* driver peer instance */ u32 pid; /* port ID of rport */ u16 maxfrsize; /* maximum frame size */ - u16 reply_oxid; /* OX_ID of inbound requests */ + __be16 reply_oxid; /* OX_ID of inbound requests */ enum fc_cos fc_cos; /* FC classes of service supp */ bfa_boolean_t cisc; /* CISC capable device */ bfa_boolean_t prlo; /* processing prlo or LOGO */ @@ -471,7 +471,7 @@ void bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port, void bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs, struct fc_logi_s *plogi); void bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport); -void bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, u16 ox_id); +void bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, __be16 ox_id); void bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport); void bfa_fcs_rport_itntm_ack(struct bfa_fcs_rport_s *rport); @@ -618,7 +618,7 @@ struct bfa_fcs_fdmi_hba_attr_s { u8 option_rom_ver[BFA_VERSION_LEN]; u8 fw_version[8]; u8 os_name[256]; - u32 max_ct_pyld; + __be32 max_ct_pyld; }; /* @@ -626,9 +626,9 @@ struct bfa_fcs_fdmi_hba_attr_s { */ struct bfa_fcs_fdmi_port_attr_s { u8 supp_fc4_types[32]; /* supported FC4 types */ - u32 supp_speed; /* supported speed */ - u32 curr_speed; /* current Speed */ - u32 max_frm_size; /* max frame size */ + __be32 supp_speed; /* supported speed */ + __be32 curr_speed; /* current Speed */ + __be32 max_frm_size; /* max frame size */ u8 os_device_name[256]; /* OS device Name */ u8 host_name[256]; /* host name */ }; diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c index 30665c744462..93c3588c715f 100644 --- a/drivers/scsi/bfa/bfa_fcs_lport.c +++ b/drivers/scsi/bfa/bfa_fcs_lport.c @@ -1569,6 +1569,7 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld) struct fdmi_attr_s *attr; u8 *curr_ptr; u16 len, count; + u16 templen; /* * get hba attributes @@ -1594,69 +1595,69 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld) */ attr = (struct fdmi_attr_s *) curr_ptr; attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODENAME); - attr->len = sizeof(wwn_t); - memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), attr->len); - curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; - len += attr->len; + templen = sizeof(wwn_t); + memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), templen); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; count++; - attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + - sizeof(attr->len)); + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); /* * Manufacturer */ attr = (struct fdmi_attr_s *) curr_ptr; attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MANUFACTURER); - attr->len = (u16) strlen(fcs_hba_attr->manufacturer); - memcpy(attr->value, fcs_hba_attr->manufacturer, attr->len); - attr->len = fc_roundup(attr->len, sizeof(u32)); - curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; - len += attr->len; + templen = (u16) strlen(fcs_hba_attr->manufacturer); + memcpy(attr->value, fcs_hba_attr->manufacturer, templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; count++; - attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + - sizeof(attr->len)); + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); /* * Serial Number */ attr = (struct fdmi_attr_s *) curr_ptr; attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_SERIALNUM); - attr->len = (u16) strlen(fcs_hba_attr->serial_num); - memcpy(attr->value, fcs_hba_attr->serial_num, attr->len); - attr->len = fc_roundup(attr->len, sizeof(u32)); - curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; - len += attr->len; + templen = (u16) strlen(fcs_hba_attr->serial_num); + memcpy(attr->value, fcs_hba_attr->serial_num, templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; count++; - attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + - sizeof(attr->len)); + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); /* * Model */ attr = (struct fdmi_attr_s *) curr_ptr; attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL); - attr->len = (u16) strlen(fcs_hba_attr->model); - memcpy(attr->value, fcs_hba_attr->model, attr->len); - attr->len = fc_roundup(attr->len, sizeof(u32)); - curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; - len += attr->len; + templen = (u16) strlen(fcs_hba_attr->model); + memcpy(attr->value, fcs_hba_attr->model, templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; count++; - attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + - sizeof(attr->len)); + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); /* * Model Desc */ attr = (struct fdmi_attr_s *) curr_ptr; attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL_DESC); - attr->len = (u16) strlen(fcs_hba_attr->model_desc); - memcpy(attr->value, fcs_hba_attr->model_desc, attr->len); - attr->len = fc_roundup(attr->len, sizeof(u32)); - curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; - len += attr->len; + templen = (u16) strlen(fcs_hba_attr->model_desc); + memcpy(attr->value, fcs_hba_attr->model_desc, templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; count++; - attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + - sizeof(attr->len)); + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); /* * H/W Version @@ -1664,14 +1665,14 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld) if (fcs_hba_attr->hw_version[0] != '\0') { attr = (struct fdmi_attr_s *) curr_ptr; attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_HW_VERSION); - attr->len = (u16) strlen(fcs_hba_attr->hw_version); - memcpy(attr->value, fcs_hba_attr->hw_version, attr->len); - attr->len = fc_roundup(attr->len, sizeof(u32)); - curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; - len += attr->len; + templen = (u16) strlen(fcs_hba_attr->hw_version); + memcpy(attr->value, fcs_hba_attr->hw_version, templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; count++; - attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + - sizeof(attr->len)); + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); } /* @@ -1679,14 +1680,14 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld) */ attr = (struct fdmi_attr_s *) curr_ptr; attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_DRIVER_VERSION); - attr->len = (u16) strlen(fcs_hba_attr->driver_version); - memcpy(attr->value, fcs_hba_attr->driver_version, attr->len); - attr->len = fc_roundup(attr->len, sizeof(u32)); - curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; - len += attr->len;; + templen = (u16) strlen(fcs_hba_attr->driver_version); + memcpy(attr->value, fcs_hba_attr->driver_version, templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen;; count++; - attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + - sizeof(attr->len)); + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); /* * Option Rom Version @@ -1694,14 +1695,14 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld) if (fcs_hba_attr->option_rom_ver[0] != '\0') { attr = (struct fdmi_attr_s *) curr_ptr; attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_ROM_VERSION); - attr->len = (u16) strlen(fcs_hba_attr->option_rom_ver); - memcpy(attr->value, fcs_hba_attr->option_rom_ver, attr->len); - attr->len = fc_roundup(attr->len, sizeof(u32)); - curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; - len += attr->len; + templen = (u16) strlen(fcs_hba_attr->option_rom_ver); + memcpy(attr->value, fcs_hba_attr->option_rom_ver, templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; count++; - attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + - sizeof(attr->len)); + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); } /* @@ -1709,14 +1710,14 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld) */ attr = (struct fdmi_attr_s *) curr_ptr; attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FW_VERSION); - attr->len = (u16) strlen(fcs_hba_attr->driver_version); - memcpy(attr->value, fcs_hba_attr->driver_version, attr->len); - attr->len = fc_roundup(attr->len, sizeof(u32)); - curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; - len += attr->len; + templen = (u16) strlen(fcs_hba_attr->driver_version); + memcpy(attr->value, fcs_hba_attr->driver_version, templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; count++; - attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + - sizeof(attr->len)); + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); /* * OS Name @@ -1724,14 +1725,14 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld) if (fcs_hba_attr->os_name[0] != '\0') { attr = (struct fdmi_attr_s *) curr_ptr; attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_OS_NAME); - attr->len = (u16) strlen(fcs_hba_attr->os_name); - memcpy(attr->value, fcs_hba_attr->os_name, attr->len); - attr->len = fc_roundup(attr->len, sizeof(u32)); - curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; - len += attr->len; + templen = (u16) strlen(fcs_hba_attr->os_name); + memcpy(attr->value, fcs_hba_attr->os_name, templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; count++; - attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + - sizeof(attr->len)); + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); } /* @@ -1739,12 +1740,12 @@ bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld) */ attr = (struct fdmi_attr_s *) curr_ptr; attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MAX_CT); - attr->len = sizeof(fcs_hba_attr->max_ct_pyld); - memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, attr->len); - len += attr->len; + templen = sizeof(fcs_hba_attr->max_ct_pyld); + memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, templen); + len += templen; count++; - attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + - sizeof(attr->len)); + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); /* * Update size of payload @@ -1845,6 +1846,7 @@ bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *curr_ptr; u16 len; u8 count = 0; + u16 templen; /* * get port attributes @@ -1863,54 +1865,54 @@ bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi, */ attr = (struct fdmi_attr_s *) curr_ptr; attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FC4_TYPES); - attr->len = sizeof(fcs_port_attr.supp_fc4_types); - memcpy(attr->value, fcs_port_attr.supp_fc4_types, attr->len); - curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; - len += attr->len; + templen = sizeof(fcs_port_attr.supp_fc4_types); + memcpy(attr->value, fcs_port_attr.supp_fc4_types, templen); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; ++count; attr->len = - cpu_to_be16(attr->len + sizeof(attr->type) + - sizeof(attr->len)); + cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); /* * Supported Speed */ attr = (struct fdmi_attr_s *) curr_ptr; attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_SPEED); - attr->len = sizeof(fcs_port_attr.supp_speed); - memcpy(attr->value, &fcs_port_attr.supp_speed, attr->len); - curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; - len += attr->len; + templen = sizeof(fcs_port_attr.supp_speed); + memcpy(attr->value, &fcs_port_attr.supp_speed, templen); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; ++count; attr->len = - cpu_to_be16(attr->len + sizeof(attr->type) + - sizeof(attr->len)); + cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); /* * current Port Speed */ attr = (struct fdmi_attr_s *) curr_ptr; attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SPEED); - attr->len = sizeof(fcs_port_attr.curr_speed); - memcpy(attr->value, &fcs_port_attr.curr_speed, attr->len); - curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; - len += attr->len; + templen = sizeof(fcs_port_attr.curr_speed); + memcpy(attr->value, &fcs_port_attr.curr_speed, templen); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; ++count; - attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + - sizeof(attr->len)); + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); /* * max frame size */ attr = (struct fdmi_attr_s *) curr_ptr; attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FRAME_SIZE); - attr->len = sizeof(fcs_port_attr.max_frm_size); - memcpy(attr->value, &fcs_port_attr.max_frm_size, attr->len); - curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; - len += attr->len; + templen = sizeof(fcs_port_attr.max_frm_size); + memcpy(attr->value, &fcs_port_attr.max_frm_size, templen); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; ++count; - attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + - sizeof(attr->len)); + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); /* * OS Device Name @@ -1918,14 +1920,14 @@ bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi, if (fcs_port_attr.os_device_name[0] != '\0') { attr = (struct fdmi_attr_s *) curr_ptr; attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_DEV_NAME); - attr->len = (u16) strlen(fcs_port_attr.os_device_name); - memcpy(attr->value, fcs_port_attr.os_device_name, attr->len); - attr->len = fc_roundup(attr->len, sizeof(u32)); - curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; - len += attr->len; + templen = (u16) strlen(fcs_port_attr.os_device_name); + memcpy(attr->value, fcs_port_attr.os_device_name, templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; ++count; - attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + - sizeof(attr->len)); + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); } /* * Host Name @@ -1933,14 +1935,14 @@ bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi, if (fcs_port_attr.host_name[0] != '\0') { attr = (struct fdmi_attr_s *) curr_ptr; attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_HOST_NAME); - attr->len = (u16) strlen(fcs_port_attr.host_name); - memcpy(attr->value, fcs_port_attr.host_name, attr->len); - attr->len = fc_roundup(attr->len, sizeof(u32)); - curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; - len += attr->len; + templen = (u16) strlen(fcs_port_attr.host_name); + memcpy(attr->value, fcs_port_attr.host_name, templen); + templen = fc_roundup(templen, sizeof(u32)); + curr_ptr += sizeof(attr->type) + sizeof(templen) + templen; + len += templen; ++count; - attr->len = cpu_to_be16(attr->len + sizeof(attr->type) + - sizeof(attr->len)); + attr->len = cpu_to_be16(templen + sizeof(attr->type) + + sizeof(templen)); } /* diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c index 60f2ddf23ebc..f5b5cbba3f43 100644 --- a/drivers/scsi/bfa/bfa_fcs_rport.c +++ b/drivers/scsi/bfa/bfa_fcs_rport.c @@ -2594,7 +2594,7 @@ bfa_fcs_rport_set_del_timeout(u8 rport_tmo) bfa_fcs_rport_del_timeout = rport_tmo * 1000; } void -bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, u16 ox_id) +bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, __be16 ox_id) { bfa_trc(rport->fcs, rport->pid); diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index 9f4aa391ea9d..9e82eea9b2b0 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -1683,7 +1683,8 @@ bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc) static bfa_status_t bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz) { - u32 pgnum, loff, r32; + u32 pgnum, loff; + __be32 r32; int i, len; u32 *buf = tbuf; @@ -1909,7 +1910,7 @@ bfa_ioc_is_initialized(struct bfa_ioc_s *ioc) void bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg) { - u32 *msgp = mbmsg; + __be32 *msgp = mbmsg; u32 r32; int i; diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index eb1b005e5bc7..f8ac05081aa3 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h @@ -115,8 +115,8 @@ struct bfa_dma_s { static inline void __bfa_dma_addr_set(union bfi_addr_u *dma_addr, u64 pa) { - dma_addr->a32.addr_lo = (u32) pa; - dma_addr->a32.addr_hi = (u32) (bfa_os_u32(pa)); + dma_addr->a32.addr_lo = (__be32) pa; + dma_addr->a32.addr_hi = (__be32) (bfa_os_u32(pa)); } @@ -125,8 +125,8 @@ __bfa_dma_addr_set(union bfi_addr_u *dma_addr, u64 pa) static inline void __bfa_dma_be_addr_set(union bfi_addr_u *dma_addr, u64 pa) { - dma_addr->a32.addr_lo = (u32) cpu_to_be32(pa); - dma_addr->a32.addr_hi = (u32) cpu_to_be32(bfa_os_u32(pa)); + dma_addr->a32.addr_lo = cpu_to_be32(pa); + dma_addr->a32.addr_hi = cpu_to_be32(bfa_os_u32(pa)); } struct bfa_ioc_regs_s { diff --git a/drivers/scsi/bfa/bfa_port.c b/drivers/scsi/bfa/bfa_port.c index fff96226a383..35277cb9a9e5 100644 --- a/drivers/scsi/bfa/bfa_port.c +++ b/drivers/scsi/bfa/bfa_port.c @@ -29,7 +29,7 @@ static void bfa_port_stats_swap(struct bfa_port_s *port, union bfa_port_stats_u *stats) { u32 *dip = (u32 *) stats; - u32 t0, t1; + __be32 t0, t1; int i; for (i = 0; i < sizeof(union bfa_port_stats_u)/sizeof(u32); diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c index 37e16ac8f249..04b3349ad3a1 100644 --- a/drivers/scsi/bfa/bfa_svc.c +++ b/drivers/scsi/bfa/bfa_svc.c @@ -3127,7 +3127,7 @@ bfa_fcport_qos_stats_swap(struct bfa_qos_stats_s *d, struct bfa_qos_stats_s *s) { u32 *dip = (u32 *) d; - u32 *sip = (u32 *) s; + __be32 *sip = (__be32 *) s; int i; /* Now swap the 32 bit fields */ @@ -3140,7 +3140,7 @@ bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s *d, struct bfa_fcoe_stats_s *s) { u32 *dip = (u32 *) d; - u32 *sip = (u32 *) s; + __be32 *sip = (__be32 *) s; int i; for (i = 0; i < ((sizeof(struct bfa_fcoe_stats_s))/sizeof(u32)); diff --git a/drivers/scsi/bfa/bfi.h b/drivers/scsi/bfa/bfi.h index 58796d1284b7..27b33c765ddc 100644 --- a/drivers/scsi/bfa/bfi.h +++ b/drivers/scsi/bfa/bfi.h @@ -95,8 +95,8 @@ enum { */ union bfi_addr_u { struct { - u32 addr_lo; - u32 addr_hi; + __be32 addr_lo; + __be32 addr_hi; } a32; }; diff --git a/drivers/scsi/bfa/bfi_ms.h b/drivers/scsi/bfa/bfi_ms.h index fa9f6fb9d45b..10288764439d 100644 --- a/drivers/scsi/bfa/bfi_ms.h +++ b/drivers/scsi/bfa/bfi_ms.h @@ -47,10 +47,10 @@ struct bfi_iocfc_cfg_s { */ union bfi_addr_u req_cq_ba[BFI_IOC_MAX_CQS]; union bfi_addr_u req_shadow_ci[BFI_IOC_MAX_CQS]; - u16 req_cq_elems[BFI_IOC_MAX_CQS]; + __be16 req_cq_elems[BFI_IOC_MAX_CQS]; union bfi_addr_u rsp_cq_ba[BFI_IOC_MAX_CQS]; union bfi_addr_u rsp_shadow_pi[BFI_IOC_MAX_CQS]; - u16 rsp_cq_elems[BFI_IOC_MAX_CQS]; + __be16 rsp_cq_elems[BFI_IOC_MAX_CQS]; union bfi_addr_u stats_addr; /* DMA-able address for stats */ union bfi_addr_u cfgrsp_addr; /* config response dma address */ @@ -102,8 +102,8 @@ struct bfi_iocfc_set_intr_req_s { struct bfi_mhdr_s mh; /* common msg header */ u8 coalesce; /* enable intr coalescing */ u8 rsvd[3]; - u16 delay; /* delay timer 0..1125us */ - u16 latency; /* latency timer 0..225us */ + __be16 delay; /* delay timer 0..1125us */ + __be16 latency; /* latency timer 0..225us */ }; @@ -210,7 +210,7 @@ struct bfi_fcport_enable_req_s { */ struct bfi_fcport_set_svc_params_req_s { struct bfi_mhdr_s mh; /* msg header */ - u16 tx_bbcredit; /* Tx credits */ + __be16 tx_bbcredit; /* Tx credits */ u16 rsvd; }; @@ -231,7 +231,7 @@ struct bfi_fcport_trunk_link_s { u8 state; /* bfa_trunk_link_state_t */ u8 speed; /* bfa_port_speed_t */ u8 rsvd; - u32 deskew; + __be32 deskew; }; #define BFI_FCPORT_MAX_LINKS 2 @@ -284,17 +284,17 @@ enum bfi_fcxp_i2h { */ struct bfi_fcxp_send_req_s { struct bfi_mhdr_s mh; /* Common msg header */ - u16 fcxp_tag; /* driver request tag */ - u16 max_frmsz; /* max send frame size */ - u16 vf_id; /* vsan tag if applicable */ + __be16 fcxp_tag; /* driver request tag */ + __be16 max_frmsz; /* max send frame size */ + __be16 vf_id; /* vsan tag if applicable */ u16 rport_fw_hndl; /* FW Handle for the remote port */ u8 class; /* FC class used for req/rsp */ u8 rsp_timeout; /* timeout in secs, 0-no response */ u8 cts; /* continue sequence */ u8 lp_tag; /* lport tag */ struct fchs_s fchs; /* request FC header structure */ - u32 req_len; /* request payload length */ - u32 rsp_maxlen; /* max response length expected */ + __be32 req_len; /* request payload length */ + __be32 rsp_maxlen; /* max response length expected */ struct bfi_sge_s req_sge[BFA_FCXP_MAX_SGES]; /* request buf */ struct bfi_sge_s rsp_sge[BFA_FCXP_MAX_SGES]; /* response buf */ }; @@ -304,11 +304,11 @@ struct bfi_fcxp_send_req_s { */ struct bfi_fcxp_send_rsp_s { struct bfi_mhdr_s mh; /* Common msg header */ - u16 fcxp_tag; /* send request tag */ + __be16 fcxp_tag; /* send request tag */ u8 req_status; /* request status */ u8 rsvd; - u32 rsp_len; /* actual response length */ - u32 residue_len; /* residual response length */ + __be32 rsp_len; /* actual response length */ + __be32 residue_len; /* residual response length */ struct fchs_s fchs; /* response FC header structure */ }; @@ -325,7 +325,7 @@ enum bfi_uf_i2h { struct bfi_uf_buf_post_s { struct bfi_mhdr_s mh; /* Common msg header */ u16 buf_tag; /* buffer tag */ - u16 buf_len; /* total buffer length */ + __be16 buf_len; /* total buffer length */ struct bfi_sge_s sge[BFA_UF_MAX_SGES]; /* buffer DMA SGEs */ }; @@ -352,7 +352,7 @@ struct bfi_lps_login_req_s { struct bfi_mhdr_s mh; /* common msg header */ u8 lp_tag; u8 alpa; - u16 pdu_size; + __be16 pdu_size; wwn_t pwwn; wwn_t nwwn; u8 fdisc; @@ -368,7 +368,7 @@ struct bfi_lps_login_rsp_s { u8 lsrjt_expl; wwn_t port_name; wwn_t node_name; - u16 bb_credit; + __be16 bb_credit; u8 f_port; u8 npiv_en; u32 lp_pid:24; @@ -427,7 +427,7 @@ enum bfi_rport_i2h_msgs { struct bfi_rport_create_req_s { struct bfi_mhdr_s mh; /* common msg header */ u16 bfa_handle; /* host rport handle */ - u16 max_frmsz; /* max rcv pdu size */ + __be16 max_frmsz; /* max rcv pdu size */ u32 pid:24, /* remote port ID */ lp_tag:8; /* local port tag */ u32 local_pid:24, /* local port ID */ @@ -583,7 +583,7 @@ struct bfi_ioim_dif_s { */ struct bfi_ioim_req_s { struct bfi_mhdr_s mh; /* Common msg header */ - u16 io_tag; /* I/O tag */ + __be16 io_tag; /* I/O tag */ u16 rport_hdl; /* itnim/rport firmware handle */ struct fcp_cmnd_s cmnd; /* IO request info */ @@ -689,7 +689,7 @@ enum bfi_ioim_status { */ struct bfi_ioim_rsp_s { struct bfi_mhdr_s mh; /* common msg header */ - u16 io_tag; /* completed IO tag */ + __be16 io_tag; /* completed IO tag */ u16 bfa_rport_hndl; /* releated rport handle */ u8 io_status; /* IO completion status */ u8 reuse_io_tag; /* IO tag can be reused */ @@ -698,13 +698,13 @@ struct bfi_ioim_rsp_s { u8 sns_len; /* scsi sense length */ u8 resid_flags; /* IO residue flags */ u8 rsvd_a; - u32 residue; /* IO residual length in bytes */ + __be32 residue; /* IO residual length in bytes */ u32 rsvd_b[3]; }; struct bfi_ioim_abort_req_s { struct bfi_mhdr_s mh; /* Common msg header */ - u16 io_tag; /* I/O tag */ + __be16 io_tag; /* I/O tag */ u16 abort_tag; /* unique request tag */ }; @@ -723,7 +723,7 @@ enum bfi_tskim_i2h { struct bfi_tskim_req_s { struct bfi_mhdr_s mh; /* Common msg header */ - u16 tsk_tag; /* task management tag */ + __be16 tsk_tag; /* task management tag */ u16 itn_fhdl; /* itn firmware handle */ lun_t lun; /* LU number */ u8 tm_flags; /* see enum fcp_tm_cmnd */ @@ -733,7 +733,7 @@ struct bfi_tskim_req_s { struct bfi_tskim_abortreq_s { struct bfi_mhdr_s mh; /* Common msg header */ - u16 tsk_tag; /* task management tag */ + __be16 tsk_tag; /* task management tag */ u16 rsvd; }; @@ -755,7 +755,7 @@ enum bfi_tskim_status { struct bfi_tskim_rsp_s { struct bfi_mhdr_s mh; /* Common msg header */ - u16 tsk_tag; /* task mgmt cmnd tag */ + __be16 tsk_tag; /* task mgmt cmnd tag */ u8 tsk_status; /* @ref bfi_tskim_status */ u8 rsvd; }; -- cgit v1.2.3-59-g8ed1b From 12137f5c28284cc51b5f50932c8d02a5823fcd3c Mon Sep 17 00:00:00 2001 From: Hillf Danton Date: Tue, 30 Nov 2010 16:18:01 -0800 Subject: [SCSI] libfc: remove define of fc_seq_exch in fc_exch.c The define for fc_seq_exch is unnecessary, since it also appears in scsi/libfc.h Signed-off-by: Hillf Danton Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index ec2a1aec2350..1dec59333ed6 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -108,7 +108,6 @@ struct fc_exch_mgr { atomic_t non_bls_resp; } stats; }; -#define fc_seq_exch(sp) container_of(sp, struct fc_exch, seq) /** * struct fc_exch_mgr_anchor - primary structure for list of EMs -- cgit v1.2.3-59-g8ed1b From 80e736f8a37bebeb5bff18f2aec31caab4104b8b Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Tue, 30 Nov 2010 16:18:07 -0800 Subject: [SCSI] libfc: fix NULL pointer dereference bug in fc_fcp_pkt_release This happens when then tearing down the fcoe interface with active I/O. The back trace shows dead000000200200 in RAX, i.e., LIST_POISON2, indicating that the fsp is already being dequeued, which is probably why no complaining was seen in fc_fcp_destroy() about outstanding fsp not freed, since we dequeue it in the end of fc_io_compl() before releasing it. The bug is due to the fact that we have already destroyed lport's scsi_pkt_pool while on-going i/o is still accessing it through fc_fcp_pkt_release(), like this trace or the similar code path from scsi-ml to fc_eh_abort, etc. This is fixed by moving the fc_fcp_destroy() after lport is detached from scsi-ml since fc_fcp_destroy is supposed to called only once where no lport lock is taken, otherwise the fc_fcp_pkt_release() would have to grab the lport lock. BUG: unable to handle kernel NULL pointer dereference at (null) ....... RIP: 0010:[<0000000000000000>] [<(null)>] (null) RSP: 0018:ffff8803270f7b88 EFLAGS: 00010282 RAX: dead000000200200 RBX: ffff880197d2fbc0 RCX: 0000000000005908 RDX: ffff880195ea6d08 RSI: 0000000000000282 RDI: ffff880180f4fec0 RBP: ffff8803270f7bc0 R08: ffff880197d2fbe0 R09: 0000000000000000 R10: ffff88032867f090 R11: 0000000000000000 R12: ffff880195ea6d08 R13: 0000000000000282 R14: ffff880180f4fec0 R15: 0000000000000000 FS: 0000000000000000(0000) GS:ffff8801b5820000(0000) knlGS:0000000000000000 CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b CR2: 0000000000000000 CR3: 00000001a6eae000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process fc_rport_eq (pid: 5278, threadinfo ffff8803270f6000, task ffff880326254ab0) Stack: ffffffffa02c39ca ffff8803270f7ba0 ffff88019331cbc0 ffff880197d2fbc0 0000000000000000 ffff8801a8c895e0 ffff8801a8c895e0 ffff8803270f7c10 ffffffffa02c4962 ffff8803270f7be0 ffffffff814c94ab ffff8803270f7c10 Call Trace: [] ? fc_io_compl+0x10a/0x530 [libfc] [] fc_fcp_complete_locked+0x72/0x150 [libfc] [] ? _spin_unlock_bh+0x1b/0x20 [] ? fc_exch_done+0x3f/0x60 [libfc] [] fc_fcp_retry_cmd+0x4f/0x60 [libfc] [] fc_fcp_recv+0x9b0/0xc30 [libfc] [] ? _call_console_drivers+0x4a/0x80 [] ? lock_timer_base+0x3c/0x70 [] ? try_to_del_timer_sync+0x7b/0xe0 [] fc_exch_mgr_reset+0x1df/0x250 [libfc] [] ? fc_fcp_recv+0x0/0xc30 [libfc] [] fc_rport_work+0xf2/0x4e0 [libfc] [] ? prepare_to_wait+0x4e/0x80 [] ? fc_rport_work+0x0/0x4e0 [libfc] [] worker_thread+0x170/0x2a0 [] ? autoremove_wake_function+0x0/0x40 [] ? worker_thread+0x0/0x2a0 [] kthread+0x96/0xa0 [] child_rip+0xa/0x20 [] ? kthread+0x0/0xa0 [] ? child_rip+0x0/0x20 Code: Bad RIP value. RIP [<(null)>] (null) RSP CR2: 0000000000000000 Signed-off-by: Yi Zou Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index d23a538a9dfc..9f9600b67001 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -854,7 +854,6 @@ static void fcoe_if_destroy(struct fc_lport *lport) /* Cleanup the fc_lport */ fc_lport_destroy(lport); - fc_fcp_destroy(lport); /* Stop the transmit retry timer */ del_timer_sync(&port->timer); @@ -876,6 +875,9 @@ static void fcoe_if_destroy(struct fc_lport *lport) fc_remove_host(lport->host); scsi_remove_host(lport->host); + /* Destroy lport scsi_priv */ + fc_fcp_destroy(lport); + /* There are no more rports or I/O, free the EM */ fc_exch_mgr_free(lport); -- cgit v1.2.3-59-g8ed1b From 8236554a27af870ecd1cd588d9558ccdc212037b Mon Sep 17 00:00:00 2001 From: Hillf Danton Date: Tue, 30 Nov 2010 16:18:12 -0800 Subject: [SCSI] libfc: fix mem leak in fc_exch_recv_seq_resp() There seems that ep should get released, or it will no longer get freed. Signed-off-by: Hillf Danton Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 1dec59333ed6..d0df1b2faf25 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1342,7 +1342,7 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) } if (ep->esb_stat & ESB_ST_COMPLETE) { atomic_inc(&mp->stats.xid_not_found); - goto out; + goto rel; } if (ep->rxid == FC_XID_UNKNOWN) ep->rxid = ntohs(fh->fh_rx_id); -- cgit v1.2.3-59-g8ed1b From 2034c19ce8f8503aa14cb1e763fbfe60316aaa8e Mon Sep 17 00:00:00 2001 From: Hillf Danton Date: Tue, 30 Nov 2010 16:18:17 -0800 Subject: [SCSI] libfc: tune fc_exch_em_alloc() to be O(2) For allocating new exch from pool, scanning for free slot in exch array fluctuates when exch pool is close to exhaustion. The fluctuation is smoothed, and the scan looks to be O(2). Signed-off-by: Hillf Danton Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index d0df1b2faf25..46973d6618d0 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -67,6 +67,11 @@ struct workqueue_struct *fc_exch_workqueue; struct fc_exch_pool { u16 next_index; u16 total_exches; + + /* two cache of free slot in exch array */ + u16 left; + u16 right; + spinlock_t lock; struct list_head ex_list; }; @@ -396,13 +401,23 @@ static inline void fc_exch_ptr_set(struct fc_exch_pool *pool, u16 index, static void fc_exch_delete(struct fc_exch *ep) { struct fc_exch_pool *pool; + u16 index; pool = ep->pool; spin_lock_bh(&pool->lock); WARN_ON(pool->total_exches <= 0); pool->total_exches--; - fc_exch_ptr_set(pool, (ep->xid - ep->em->min_xid) >> fc_cpu_order, - NULL); + + /* update cache of free slot */ + index = (ep->xid - ep->em->min_xid) >> fc_cpu_order; + if (pool->left == FC_XID_UNKNOWN) + pool->left = index; + else if (pool->right == FC_XID_UNKNOWN) + pool->right = index; + else + pool->next_index = index; + + fc_exch_ptr_set(pool, index, NULL); list_del(&ep->ex_list); spin_unlock_bh(&pool->lock); fc_exch_release(ep); /* drop hold for exch in mp */ @@ -678,6 +693,19 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport, pool = per_cpu_ptr(mp->pool, cpu); spin_lock_bh(&pool->lock); put_cpu(); + + /* peek cache of free slot */ + if (pool->left != FC_XID_UNKNOWN) { + index = pool->left; + pool->left = FC_XID_UNKNOWN; + goto hit; + } + if (pool->right != FC_XID_UNKNOWN) { + index = pool->right; + pool->right = FC_XID_UNKNOWN; + goto hit; + } + index = pool->next_index; /* allocate new exch from pool */ while (fc_exch_ptr_get(pool, index)) { @@ -686,7 +714,7 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport, goto err; } pool->next_index = index == mp->pool_max_index ? 0 : index + 1; - +hit: fc_exch_hold(ep); /* hold for exch in mp */ spin_lock_init(&ep->ex_lock); /* @@ -2180,6 +2208,8 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lport, goto free_mempool; for_each_possible_cpu(cpu) { pool = per_cpu_ptr(mp->pool, cpu); + pool->left = FC_XID_UNKNOWN; + pool->right = FC_XID_UNKNOWN; spin_lock_init(&pool->lock); INIT_LIST_HEAD(&pool->ex_list); } -- cgit v1.2.3-59-g8ed1b From 3c2c3bf23cbef8eed6cf815715d0bece5cb7b5ec Mon Sep 17 00:00:00 2001 From: Robert Love Date: Tue, 30 Nov 2010 16:18:23 -0800 Subject: [SCSI] libfc: Fix incorrect locking and unlocking in FCP The error handler grabs the si->scsi_queue_lock, but in the case where the fsp pointer is NULL it releases the scsi_host lock. This can lead to a variety of system hangs depending on which is used first- the scsi_host lock or the scsi_queue_lock. This patch simply unlocks the correct lock when fcp is NULL. Signed-off-by: Robert Love Tested-by: Ross Brattain Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_fcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 2924363d142b..b9ad74de76da 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -2004,7 +2004,7 @@ int fc_eh_abort(struct scsi_cmnd *sc_cmd) fsp = CMD_SP(sc_cmd); if (!fsp) { /* command completed while scsi eh was setting up */ - spin_unlock_irqrestore(lport->host->host_lock, flags); + spin_unlock_irqrestore(&si->scsi_queue_lock, flags); return SUCCESS; } /* grab a ref so the fsp and sc_cmd cannot be relased from under us */ -- cgit v1.2.3-59-g8ed1b From 530994d69e5b6b4eca2db4a21b6d945d13646053 Mon Sep 17 00:00:00 2001 From: Hillf Danton Date: Tue, 30 Nov 2010 16:18:28 -0800 Subject: [SCSI] libfc: fix mem leak in fc_seq_assign() There is a typo cleaned, which triggers memory leakage. Signed-off-by: Hillf Danton Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 46973d6618d0..8bfb421fcdd6 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1274,7 +1274,7 @@ static struct fc_seq *fc_seq_assign(struct fc_lport *lport, struct fc_frame *fp) list_for_each_entry(ema, &lport->ema_list, ema_list) if ((!ema->match || ema->match(fp)) && - fc_seq_lookup_recip(lport, ema->mp, fp) != FC_RJT_NONE) + fc_seq_lookup_recip(lport, ema->mp, fp) == FC_RJT_NONE) break; return fr_seq(fp); } -- cgit v1.2.3-59-g8ed1b From e90ff5ef0aab1d40f0e92a44d66f8d45a20d8c95 Mon Sep 17 00:00:00 2001 From: Hillf Danton Date: Tue, 30 Nov 2010 16:18:33 -0800 Subject: [SCSI] libfc: fix stats computation in fc_queuecommand() There seems accumulation needed. Signed-off-by: Hillf Danton Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_fcp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index b9ad74de76da..0e985dbaedc4 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -1820,11 +1820,11 @@ static int fc_queuecommand_lck(struct scsi_cmnd *sc_cmd, void (*done)(struct scs if (sc_cmd->sc_data_direction == DMA_FROM_DEVICE) { fsp->req_flags = FC_SRB_READ; stats->InputRequests++; - stats->InputMegabytes = fsp->data_len; + stats->InputMegabytes += fsp->data_len; } else if (sc_cmd->sc_data_direction == DMA_TO_DEVICE) { fsp->req_flags = FC_SRB_WRITE; stats->OutputRequests++; - stats->OutputMegabytes = fsp->data_len; + stats->OutputMegabytes += fsp->data_len; } else { fsp->req_flags = 0; stats->ControlRequests++; -- cgit v1.2.3-59-g8ed1b From ac17ea8d7d45d0495316edff13faa0dfd6bb2225 Mon Sep 17 00:00:00 2001 From: john fastabend Date: Tue, 30 Nov 2010 16:18:39 -0800 Subject: [SCSI] libfc: incorrect scsi host byte codes returned to scsi-ml The fcp packet recovery handler fc_fcp_recover() is called when errors occurr in a fcp session. Currently it is generically setting the status code to FC_CMD_RECOVERY for all error types. This results in DID_BUS_BUSY errors being returned to the scsi-ml. DID_BUS_BUSY errors indicate "BUS stayed busy through time out period" according to scsi.h. Many of the error reported by fc_rcp_recovery() are pkt errors. Here we update fc_fcp_recovery to use better host byte codes. With certain FAST FAIL flags set DID_BUS_BUSY and DID_ERROR will have different behaviors this was causing dm multipath to fail quickly in some cases where a retry would be a better action. Signed-off-by: John Fastabend Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_fcp.c | 61 ++++++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 0e985dbaedc4..8eb67676d0dd 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -96,7 +96,7 @@ static void fc_fcp_resp(struct fc_fcp_pkt *, struct fc_frame *); static void fc_fcp_complete_locked(struct fc_fcp_pkt *); static void fc_tm_done(struct fc_seq *, struct fc_frame *, void *); static void fc_fcp_error(struct fc_fcp_pkt *, struct fc_frame *); -static void fc_fcp_recovery(struct fc_fcp_pkt *); +static void fc_fcp_recovery(struct fc_fcp_pkt *, u8 code); static void fc_fcp_timeout(unsigned long); static void fc_fcp_rec(struct fc_fcp_pkt *); static void fc_fcp_rec_error(struct fc_fcp_pkt *, struct fc_frame *); @@ -120,7 +120,8 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *, struct fc_frame *); #define FC_DATA_UNDRUN 7 #define FC_ERROR 8 #define FC_HRD_ERROR 9 -#define FC_CMD_RECOVERY 10 +#define FC_CRC_ERROR 10 +#define FC_TIMED_OUT 11 /* * Error recovery timeout values. @@ -438,6 +439,7 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp) void *buf; struct scatterlist *sg; u32 nents; + u8 host_bcode = FC_COMPLETE; fh = fc_frame_header_get(fp); offset = ntohl(fh->fh_parm_offset); @@ -446,13 +448,16 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp) buf = fc_frame_payload_get(fp, 0); /* - * if this I/O is ddped then clear it - * and initiate recovery since data - * frames are expected to be placed - * directly in that case. + * if this I/O is ddped then clear it and initiate recovery since data + * frames are expected to be placed directly in that case. + * + * Indicate error to scsi-ml because something went wrong with the + * ddp handling to get us here. */ if (fsp->xfer_ddp != FC_XID_UNKNOWN) { fc_fcp_ddp_done(fsp); + FC_FCP_DBG(fsp, "DDP I/O in fc_fcp_recv_data set ERROR\n"); + host_bcode = FC_ERROR; goto err; } if (offset + len > fsp->data_len) { @@ -462,6 +467,9 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp) goto crc_err; FC_FCP_DBG(fsp, "data received past end. len %zx offset %zx " "data_len %x\n", len, offset, fsp->data_len); + + /* Data is corrupted indicate scsi-ml should retry */ + host_bcode = FC_DATA_OVRRUN; goto err; } if (offset != fsp->xfer_len) @@ -498,8 +506,10 @@ crc_err: * If so, we need to retry the entire operation. * Otherwise, ignore it. */ - if (fsp->state & FC_SRB_DISCONTIG) + if (fsp->state & FC_SRB_DISCONTIG) { + host_bcode = FC_CRC_ERROR; goto err; + } return; } } @@ -517,7 +527,7 @@ crc_err: fc_fcp_complete_locked(fsp); return; err: - fc_fcp_recovery(fsp); + fc_fcp_recovery(fsp, host_bcode); } /** @@ -1347,7 +1357,7 @@ static void fc_fcp_timeout(unsigned long data) else if (fsp->state & FC_SRB_RCV_STATUS) fc_fcp_complete_locked(fsp); else - fc_fcp_recovery(fsp); + fc_fcp_recovery(fsp, FC_TIMED_OUT); fsp->state &= ~FC_SRB_FCP_PROCESSING_TMO; unlock: fc_fcp_unlock_pkt(fsp); @@ -1391,7 +1401,7 @@ retry: if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV); else - fc_fcp_recovery(fsp); + fc_fcp_recovery(fsp, FC_TIMED_OUT); } /** @@ -1460,7 +1470,7 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) fc_fcp_retry_cmd(fsp); break; } - fc_fcp_recovery(fsp); + fc_fcp_recovery(fsp, FC_ERROR); break; } } else if (opcode == ELS_LS_ACC) { @@ -1575,7 +1585,7 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) fc_fcp_rec(fsp); else - fc_fcp_recovery(fsp); + fc_fcp_recovery(fsp, FC_ERROR); break; } fc_fcp_unlock_pkt(fsp); @@ -1587,9 +1597,9 @@ out: * fc_fcp_recovery() - Handler for fcp_pkt recovery * @fsp: The FCP pkt that needs to be aborted */ -static void fc_fcp_recovery(struct fc_fcp_pkt *fsp) +static void fc_fcp_recovery(struct fc_fcp_pkt *fsp, u8 code) { - fsp->status_code = FC_CMD_RECOVERY; + fsp->status_code = code; fsp->cdb_status = 0; fsp->io_status = 0; /* @@ -1695,7 +1705,7 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) break; case ELS_LS_RJT: default: - fc_fcp_recovery(fsp); + fc_fcp_recovery(fsp, FC_ERROR); break; } fc_fcp_unlock_pkt(fsp); @@ -1721,7 +1731,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) fc_fcp_rec(fsp); else - fc_fcp_recovery(fsp); + fc_fcp_recovery(fsp, FC_TIMED_OUT); break; case -FC_EX_CLOSED: /* e.g., link failure */ /* fall through */ @@ -1946,18 +1956,29 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) break; case FC_CMD_ABORTED: FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml " - "due to FC_CMD_ABORTED\n"); + "due to FC_CMD_ABORTED\n"); sc_cmd->result = (DID_ERROR << 16) | fsp->io_status; break; - case FC_CMD_RECOVERY: - sc_cmd->result = (DID_BUS_BUSY << 16) | fsp->io_status; - break; case FC_CMD_RESET: + FC_FCP_DBG(fsp, "Returning DID_RESET to scsi-ml " + "due to FC_CMD_RESET\n"); sc_cmd->result = (DID_RESET << 16); break; case FC_HRD_ERROR: + FC_FCP_DBG(fsp, "Returning DID_NO_CONNECT to scsi-ml " + "due to FC_HRD_ERROR\n"); sc_cmd->result = (DID_NO_CONNECT << 16); break; + case FC_CRC_ERROR: + FC_FCP_DBG(fsp, "Returning DID_PARITY to scsi-ml " + "due to FC_CRC_ERROR\n"); + sc_cmd->result = (DID_PARITY << 16); + break; + case FC_TIMED_OUT: + FC_FCP_DBG(fsp, "Returning DID_BUS_BUSY to scsi-ml " + "due to FC_TIMED_OUT\n"); + sc_cmd->result = (DID_BUS_BUSY << 16) | fsp->io_status; + break; default: FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml " "due to unknown error\n"); -- cgit v1.2.3-59-g8ed1b From e0883a3c3e7766b390971a49bf728004816c9520 Mon Sep 17 00:00:00 2001 From: john fastabend Date: Tue, 30 Nov 2010 16:18:44 -0800 Subject: [SCSI] libfc: use rport timeout values for fcp recovery Use the rport value for rec_tov for timeout values when sending fcp commands. Currently, defaults are being used which may or may not match the advertised values. The default may cause i/o to timeout on networks that set this value larger then the default value. To make the timeout more configurable in the non-REC mode we remove the FC_SCSI_ER_TIMEOUT completely allowing the scsi-ml to do the timeout. This removes an unneeded timer and allows the i/o timeout to be configured using the scsi-ml knobs. Signed-off-by: John Fastabend Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_fcp.c | 58 ++++++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 8eb67676d0dd..a7d956ad16e3 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -57,6 +57,9 @@ struct kmem_cache *scsi_pkt_cachep; #define FC_SRB_READ (1 << 1) #define FC_SRB_WRITE (1 << 0) +/* constant added to e_d_tov timeout to get rec_tov value */ +#define REC_TOV_CONST 1 + /* * The SCp.ptr should be tested and set under the scsi_pkt_queue lock */ @@ -126,9 +129,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *, struct fc_frame *); /* * Error recovery timeout values. */ -#define FC_SCSI_ER_TIMEOUT (10 * HZ) #define FC_SCSI_TM_TOV (10 * HZ) -#define FC_SCSI_REC_TOV (2 * HZ) #define FC_HOST_RESET_TIMEOUT (30 * HZ) #define FC_CAN_QUEUE_PERIOD (60 * HZ) @@ -1082,6 +1083,21 @@ static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp) return rc; } +/** + * get_fsp_rec_tov() - Helper function to get REC_TOV + * @fsp: the FCP packet + */ +static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp) +{ + struct fc_rport *rport; + struct fc_rport_libfc_priv *rpriv; + + rport = fsp->rport; + rpriv = rport->dd_data; + + return rpriv->e_d_tov + REC_TOV_CONST; +} + /** * fc_fcp_cmd_send() - Send a FCP command * @lport: The local port to send the command on @@ -1099,6 +1115,7 @@ static int fc_fcp_cmd_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp, struct fc_rport_libfc_priv *rpriv; const size_t len = sizeof(fsp->cdb_cmd); int rc = 0; + unsigned int rec_tov; if (fc_fcp_lock_pkt(fsp)) return 0; @@ -1129,10 +1146,12 @@ static int fc_fcp_cmd_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp, fsp->seq_ptr = seq; fc_fcp_pkt_hold(fsp); /* hold for fc_fcp_pkt_destroy */ + rec_tov = get_fsp_rec_tov(fsp); + setup_timer(&fsp->timer, fc_fcp_timeout, (unsigned long)fsp); - fc_fcp_timer_set(fsp, - (fsp->tgt_flags & FC_RP_FLAGS_REC_SUPPORTED) ? - FC_SCSI_REC_TOV : FC_SCSI_ER_TIMEOUT); + + if (fsp->tgt_flags & FC_RP_FLAGS_REC_SUPPORTED) + fc_fcp_timer_set(fsp, rec_tov); unlock: fc_fcp_unlock_pkt(fsp); return rc; @@ -1207,13 +1226,16 @@ static void fc_lun_reset_send(unsigned long data) { struct fc_fcp_pkt *fsp = (struct fc_fcp_pkt *)data; struct fc_lport *lport = fsp->lp; + unsigned int rec_tov; + if (lport->tt.fcp_cmd_send(lport, fsp, fc_tm_done)) { if (fsp->recov_retry++ >= FC_MAX_RECOV_RETRY) return; if (fc_fcp_lock_pkt(fsp)) return; + rec_tov = get_fsp_rec_tov(fsp); setup_timer(&fsp->timer, fc_lun_reset_send, (unsigned long)fsp); - fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV); + fc_fcp_timer_set(fsp, rec_tov); fc_fcp_unlock_pkt(fsp); } } @@ -1351,9 +1373,6 @@ static void fc_fcp_timeout(unsigned long data) if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED) fc_fcp_rec(fsp); - else if (time_after_eq(fsp->last_pkt_time + (FC_SCSI_ER_TIMEOUT / 2), - jiffies)) - fc_fcp_timer_set(fsp, FC_SCSI_ER_TIMEOUT); else if (fsp->state & FC_SRB_RCV_STATUS) fc_fcp_complete_locked(fsp); else @@ -1373,6 +1392,7 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp) struct fc_frame *fp; struct fc_rport *rport; struct fc_rport_libfc_priv *rpriv; + unsigned int rec_tov; lport = fsp->lp; rport = fsp->rport; @@ -1383,6 +1403,9 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp) fc_fcp_complete_locked(fsp); return; } + + rec_tov = get_fsp_rec_tov(fsp); + fp = fc_fcp_frame_alloc(lport, sizeof(struct fc_els_rec)); if (!fp) goto retry; @@ -1393,13 +1416,13 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp) FC_FCTL_REQ, 0); if (lport->tt.elsct_send(lport, rport->port_id, fp, ELS_REC, fc_fcp_rec_resp, fsp, - jiffies_to_msecs(FC_SCSI_REC_TOV))) { + jiffies_to_msecs(rec_tov))) { fc_fcp_pkt_hold(fsp); /* hold while REC outstanding */ return; } retry: if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) - fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV); + fc_fcp_timer_set(fsp, rec_tov); else fc_fcp_recovery(fsp, FC_TIMED_OUT); } @@ -1455,7 +1478,6 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) * making progress. */ rpriv->flags &= ~FC_RP_FLAGS_REC_SUPPORTED; - fc_fcp_timer_set(fsp, FC_SCSI_ER_TIMEOUT); break; case ELS_RJT_LOGIC: case ELS_RJT_UNAB: @@ -1508,12 +1530,12 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) } fc_fcp_srr(fsp, r_ctl, offset); } else if (e_stat & ESB_ST_SEQ_INIT) { - + unsigned int rec_tov = get_fsp_rec_tov(fsp); /* * The remote port has the initiative, so just * keep waiting for it to complete. */ - fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV); + fc_fcp_timer_set(fsp, rec_tov); } else { /* @@ -1626,6 +1648,7 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) struct fcp_srr *srr; struct fc_frame *fp; u8 cdb_op; + unsigned int rec_tov; rport = fsp->rport; rpriv = rport->dd_data; @@ -1650,8 +1673,9 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) rpriv->local_port->port_id, FC_TYPE_FCP, FC_FCTL_REQ, 0); + rec_tov = get_fsp_rec_tov(fsp); seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp, NULL, - fsp, jiffies_to_msecs(FC_SCSI_REC_TOV)); + fsp, jiffies_to_msecs(rec_tov)); if (!seq) goto retry; @@ -1675,6 +1699,7 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) { struct fc_fcp_pkt *fsp = arg; struct fc_frame_header *fh; + unsigned int rec_tov; if (IS_ERR(fp)) { fc_fcp_srr_error(fsp, fp); @@ -1701,7 +1726,8 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) switch (fc_frame_payload_op(fp)) { case ELS_LS_ACC: fsp->recov_retry = 0; - fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV); + rec_tov = get_fsp_rec_tov(fsp); + fc_fcp_timer_set(fsp, rec_tov); break; case ELS_LS_RJT: default: -- cgit v1.2.3-59-g8ed1b From 05fee645e96e732a79ad083cab8ddd4efd108e2c Mon Sep 17 00:00:00 2001 From: john fastabend Date: Tue, 30 Nov 2010 16:18:49 -0800 Subject: [SCSI] libfc: remove tgt_flags from fc_fcp_pkt struct We can easily remove the tgt_flags from fc_fcp_pkt struct and use rpriv->tgt_flags directly where needed. Signed-off-by: John Fastabend Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_fcp.c | 5 ++--- include/scsi/libfc.h | 2 -- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index a7d956ad16e3..a36c652edbba 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -1150,8 +1150,9 @@ static int fc_fcp_cmd_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp, setup_timer(&fsp->timer, fc_fcp_timeout, (unsigned long)fsp); - if (fsp->tgt_flags & FC_RP_FLAGS_REC_SUPPORTED) + if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED) fc_fcp_timer_set(fsp, rec_tov); + unlock: fc_fcp_unlock_pkt(fsp); return rc; @@ -1867,8 +1868,6 @@ static int fc_queuecommand_lck(struct scsi_cmnd *sc_cmd, void (*done)(struct scs } put_cpu(); - fsp->tgt_flags = rpriv->flags; - init_timer(&fsp->timer); fsp->timer.data = (unsigned long)fsp; diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 5c4c1678f7be..3eb3915eb557 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -263,7 +263,6 @@ struct fc_seq_els_data { * struct fc_fcp_pkt - FCP request structure (one for each scsi_cmnd request) * @lp: The associated local port * @state: The state of the I/O - * @tgt_flags: Target's flags * @ref_cnt: Reference count * @scsi_pkt_lock: Lock to protect the SCSI packet (must be taken before the * host_lock if both are to be held at the same time) @@ -298,7 +297,6 @@ struct fc_fcp_pkt { /* Housekeeping information */ struct fc_lport *lp; u16 state; - u16 tgt_flags; atomic_t ref_cnt; spinlock_t scsi_pkt_lock; -- cgit v1.2.3-59-g8ed1b From 2d6dfb005e24d7e3404f4c0d333a94b050059173 Mon Sep 17 00:00:00 2001 From: Hillf Danton Date: Tue, 30 Nov 2010 16:18:54 -0800 Subject: [SCSI] libfc: fix memory leakage in local port There seems info should get freed when error encountered. Signed-off-by: Hillf Danton Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_lport.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 9be63edbf8fb..9c1d6b8b24a3 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1762,8 +1762,10 @@ static int fc_lport_ct_request(struct fc_bsg_job *job, info->sg = job->reply_payload.sg_list; if (!lport->tt.exch_seq_send(lport, fp, fc_lport_bsg_resp, - NULL, info, tov)) + NULL, info, tov)) { + kfree(info); return -ECOMM; + } return 0; } -- cgit v1.2.3-59-g8ed1b From 72e0daad555bc0ca2e7abd68593087d098d866a8 Mon Sep 17 00:00:00 2001 From: Hillf Danton Date: Tue, 30 Nov 2010 16:18:59 -0800 Subject: [SCSI] libfc: fix memory leakage in local port There seems info should get freed when error encountered. Signed-off-by: Hillf Danton Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_lport.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 9c1d6b8b24a3..b91a11e4fa06 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1703,8 +1703,10 @@ static int fc_lport_els_request(struct fc_bsg_job *job, info->sg = job->reply_payload.sg_list; if (!lport->tt.exch_seq_send(lport, fp, fc_lport_bsg_resp, - NULL, info, tov)) + NULL, info, tov)) { + kfree(info); return -ECOMM; + } return 0; } -- cgit v1.2.3-59-g8ed1b From 0e9e3d3b155c35d5750805c2b8bb6d5b6e6a3bfb Mon Sep 17 00:00:00 2001 From: Hillf Danton Date: Tue, 30 Nov 2010 16:19:04 -0800 Subject: [SCSI] libfc: fix memory leakage in remote port There seems rdata should get put before return. Signed-off-by: Hillf Danton Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_rport.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index a84ef13ed74a..a7175adab32d 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -652,7 +652,7 @@ void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, FC_RPORT_DBG(rdata, "Received a FLOGI %s\n", fc_els_resp_type(fp)); if (fp == ERR_PTR(-FC_EX_CLOSED)) - return; + goto put; mutex_lock(&rdata->rp_mutex); @@ -689,6 +689,7 @@ out: fc_frame_free(fp); err: mutex_unlock(&rdata->rp_mutex); +put: kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); return; bad: -- cgit v1.2.3-59-g8ed1b From 11aa99001afdbe5fe152e833aa1fea82b85dbeda Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 30 Nov 2010 16:19:09 -0800 Subject: [SCSI] drivers/scsi/fcoe: Update WARN uses Add missing newlines. Signed-off-by: Joe Perches Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index bc17c7123202..58ad3c7a454f 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -2475,7 +2475,7 @@ static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip) case FIP_ST_LINK_WAIT: goto unlock; default: - WARN(1, "unexpected state %d", fip->state); + WARN(1, "unexpected state %d\n", fip->state); goto unlock; } mod_timer(&fip->timer, next_time); -- cgit v1.2.3-59-g8ed1b From 9b90dc80ba2e566a48585174b1e5ab00e16f0456 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Tue, 30 Nov 2010 16:19:15 -0800 Subject: [SCSI] libfc: add print of exchange id for debugging fc_fcp This is very helpful to match up the corresponding exchange to the actual I/O described by the fsp, particularly when you do a side-by-side comparison of the syslog with your trace. Signed-off-by: Yi Zou Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_libfc.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libfc/fc_libfc.h b/drivers/scsi/libfc/fc_libfc.h index 16d2162dda1f..eea0c3541b71 100644 --- a/drivers/scsi/libfc/fc_libfc.h +++ b/drivers/scsi/libfc/fc_libfc.h @@ -66,9 +66,21 @@ extern unsigned int fc_debug_logging; #define FC_FCP_DBG(pkt, fmt, args...) \ FC_CHECK_LOGGING(FC_FCP_LOGGING, \ - printk(KERN_INFO "host%u: fcp: %6.6x: " fmt, \ + { \ + if ((pkt)->seq_ptr) { \ + struct fc_exch *_ep = NULL; \ + _ep = fc_seq_exch((pkt)->seq_ptr); \ + printk(KERN_INFO "host%u: fcp: %6.6x: " \ + "xid %04x-%04x: " fmt, \ (pkt)->lp->host->host_no, \ - pkt->rport->port_id, ##args)) + (pkt)->rport->port_id, \ + (_ep)->oxid, (_ep)->rxid, ##args); \ + } else { \ + printk(KERN_INFO "host%u: fcp: %6.6x: " fmt, \ + (pkt)->lp->host->host_no, \ + (pkt)->rport->port_id, ##args); \ + } \ + }) #define FC_EXCH_DBG(exch, fmt, args...) \ FC_CHECK_LOGGING(FC_EXCH_LOGGING, \ -- cgit v1.2.3-59-g8ed1b From d889b30a9196c453120ca54323fe80acb4c27b94 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Tue, 30 Nov 2010 16:19:20 -0800 Subject: [SCSI] libfc: do not fc_io_compl on fsp w/o any scsi_cmnd associated Do not call fc_io_compl() on fsp w/o any scsi_cmnd, e.g., lun reset is built inside fc_fcp, not from a scsi command from queuecommnd from scsi-ml, so in in case target is buggy that is invalid flags in the FCP_RSP, as we have seen in some SAN Blaze target where all bits in flags are 0, we do not want to call io_compl on this fsp. [ Comment block added by Robert Love ] Signed-off-by: Yi Zou Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_fcp.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index a36c652edbba..47c930a01454 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -973,7 +973,13 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp) } lport->tt.exch_done(seq); } - fc_io_compl(fsp); + /* + * Some resets driven by SCSI are not I/Os and do not have + * SCSI commands associated with the requests. We should not + * call I/O completion if we do not have a SCSI command. + */ + if (fsp->cmd) + fc_io_compl(fsp); } /** -- cgit v1.2.3-59-g8ed1b From ea3e2e72eeb3e8a9440a5da965914f9b12088626 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Tue, 30 Nov 2010 16:19:25 -0800 Subject: [SCSI] libfc: fix exchange being deleted when the abort itself is timed out Should not continue when the abort itself is being timeout since in that case the exchange will be deleted and relesased. We still want to call the associated response handler to let the layer, e.g., fcp, know the exchange itself is being timed out. Signed-off-by: Yi Zou Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 8bfb421fcdd6..d21367d3305f 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -650,10 +650,13 @@ static void fc_exch_timeout(struct work_struct *work) if (e_stat & ESB_ST_ABNORMAL) rc = fc_exch_done_locked(ep); spin_unlock_bh(&ep->ex_lock); - if (!rc) - fc_exch_delete(ep); if (resp) resp(sp, ERR_PTR(-FC_EX_TIMEOUT), arg); + if (!rc) { + /* delete the exchange if it's already being aborted */ + fc_exch_delete(ep); + return; + } fc_seq_exch_abort(sp, 2 * ep->r_a_tov); goto done; } -- cgit v1.2.3-59-g8ed1b From 3a91090fe0df10091c5612db8528ee7a822ab83d Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Tue, 30 Nov 2010 16:19:30 -0800 Subject: [SCSI] libfc: the timeout for the REC itself is 2 * R_A_TOV_els The timeout for the exchange carrying REC itself is 2 * R_A_TOV_els. Signed-off-by: Yi Zou Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_fcp.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 47c930a01454..338620b33fa1 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -1399,7 +1399,6 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp) struct fc_frame *fp; struct fc_rport *rport; struct fc_rport_libfc_priv *rpriv; - unsigned int rec_tov; lport = fsp->lp; rport = fsp->rport; @@ -1411,8 +1410,6 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp) return; } - rec_tov = get_fsp_rec_tov(fsp); - fp = fc_fcp_frame_alloc(lport, sizeof(struct fc_els_rec)); if (!fp) goto retry; @@ -1423,13 +1420,13 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp) FC_FCTL_REQ, 0); if (lport->tt.elsct_send(lport, rport->port_id, fp, ELS_REC, fc_fcp_rec_resp, fsp, - jiffies_to_msecs(rec_tov))) { + 2 * lport->r_a_tov)) { fc_fcp_pkt_hold(fsp); /* hold while REC outstanding */ return; } retry: if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) - fc_fcp_timer_set(fsp, rec_tov); + fc_fcp_timer_set(fsp, get_fsp_rec_tov(fsp)); else fc_fcp_recovery(fsp, FC_TIMED_OUT); } -- cgit v1.2.3-59-g8ed1b From b5fe5e953c65cd0ec4e9ffd001072700e5b89317 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Tue, 30 Nov 2010 16:19:35 -0800 Subject: [SCSI] libfc: fix fc_tm_done not freeing the allocated fsp pkt Frame should be freed in fc_tm_done, this is an updated patch on the one initially submitted by Hillf Danton. Signed-off-by: Hillf Danton Signed-off-by: Yi Zou Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_fcp.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 338620b33fa1..a8e0c0acc736 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -1321,27 +1321,27 @@ static void fc_tm_done(struct fc_seq *seq, struct fc_frame *fp, void *arg) * * scsi-eh will escalate for when either happens. */ - return; + goto out; } if (fc_fcp_lock_pkt(fsp)) - return; + goto out; /* * raced with eh timeout handler. */ - if (!fsp->seq_ptr || !fsp->wait_for_comp) { - spin_unlock_bh(&fsp->scsi_pkt_lock); - return; - } + if (!fsp->seq_ptr || !fsp->wait_for_comp) + goto out_unlock; fh = fc_frame_header_get(fp); if (fh->fh_type != FC_TYPE_BLS) fc_fcp_resp(fsp, fp); fsp->seq_ptr = NULL; fsp->lp->tt.exch_done(seq); - fc_frame_free(fp); +out_unlock: fc_fcp_unlock_pkt(fsp); +out: + fc_frame_free(fp); } /** -- cgit v1.2.3-59-g8ed1b From 69316ee2e375c5af0cf1f8d2d30f9aa277f0b454 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 30 Nov 2010 16:19:40 -0800 Subject: [SCSI] libfcoe: update FIP FCF announcements Move the announcement code to a separate function for reuse in a forthcoming patch. For messages regarding FCF timeout and selection, use the previously-announced FCF MAC address (dest_addr) in the fcoe_ctlr struct. Only print (announce) the FCF if it is new. Print MAC for timed-out or deselected FCFs. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 58ad3c7a454f..26381f00e4e5 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -230,6 +230,33 @@ void fcoe_ctlr_destroy(struct fcoe_ctlr *fip) } EXPORT_SYMBOL(fcoe_ctlr_destroy); +/** + * fcoe_ctlr_announce() - announce new selection + * @fip: The FCoE controller + * + * Also sets the destination MAC for FCoE and control packets + */ +static void fcoe_ctlr_announce(struct fcoe_ctlr *fip) +{ + struct fcoe_fcf *sel = fip->sel_fcf; + + if (sel && !compare_ether_addr(sel->fcf_mac, fip->dest_addr)) + return; + if (!is_zero_ether_addr(fip->dest_addr)) { + printk(KERN_NOTICE "libfcoe: host%d: " + "FIP Fibre-Channel Forwarder MAC %pM deselected\n", + fip->lp->host->host_no, fip->dest_addr); + memset(fip->dest_addr, 0, ETH_ALEN); + } + if (sel) { + printk(KERN_INFO "libfcoe: host%d: FIP selected " + "Fibre-Channel Forwarder MAC %pM\n", + fip->lp->host->host_no, sel->fcf_mac); + memcpy(fip->dest_addr, sel->fcf_mac, ETH_ALEN); + fip->map_dest = 0; + } +} + /** * fcoe_ctlr_fcoe_size() - Return the maximum FCoE size required for VN_Port * @fip: The FCoE controller to get the maximum FCoE size from @@ -1420,24 +1447,15 @@ static void fcoe_ctlr_timer_work(struct work_struct *work) if (sel != fcf) { fcf = sel; /* the old FCF may have been freed */ + fcoe_ctlr_announce(fip); if (sel) { - printk(KERN_INFO "libfcoe: host%d: FIP selected " - "Fibre-Channel Forwarder MAC %pM\n", - fip->lp->host->host_no, sel->fcf_mac); - memcpy(fip->dest_addr, sel->fcf_mac, ETH_ALEN); - fip->map_dest = 0; fip->port_ka_time = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); fip->ctlr_ka_time = jiffies + sel->fka_period; if (time_after(next_timer, fip->ctlr_ka_time)) next_timer = fip->ctlr_ka_time; - } else { - printk(KERN_NOTICE "libfcoe: host%d: " - "FIP Fibre-Channel Forwarder timed out. " - "Starting FCF discovery.\n", - fip->lp->host->host_no); + } else reset = 1; - } } if (sel && !sel->fd_flags) { -- cgit v1.2.3-59-g8ed1b From c47036a7cd378533495d8cc06a7cf8a881072a9d Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 30 Nov 2010 16:19:46 -0800 Subject: [SCSI] libfcoe: move some timer code to make it reusable. Move some of the code in fcoe_ctlr_timer_work() to fcoe_ctlr_select() so that it can be shared with another function in a forthcoming patch. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 26381f00e4e5..4d0be20cb73d 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -1391,6 +1391,13 @@ static void fcoe_ctlr_select(struct fcoe_ctlr *fip) best = fcf; } fip->sel_fcf = best; + if (best) { + fip->port_ka_time = jiffies + + msecs_to_jiffies(FIP_VN_KA_PERIOD); + fip->ctlr_ka_time = jiffies + best->fka_period; + if (time_before(fip->ctlr_ka_time, fip->timer.expires)) + mod_timer(&fip->timer, fip->ctlr_ka_time); + } } /** @@ -1449,9 +1456,6 @@ static void fcoe_ctlr_timer_work(struct work_struct *work) fcf = sel; /* the old FCF may have been freed */ fcoe_ctlr_announce(fip); if (sel) { - fip->port_ka_time = jiffies + - msecs_to_jiffies(FIP_VN_KA_PERIOD); - fip->ctlr_ka_time = jiffies + sel->fka_period; if (time_after(next_timer, fip->ctlr_ka_time)) next_timer = fip->ctlr_ka_time; } else -- cgit v1.2.3-59-g8ed1b From b69ae0ae3f322d9a6bc4e209049b5b6e193ad652 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 30 Nov 2010 16:19:51 -0800 Subject: [SCSI] libfcoe: fix checking of conflicting fabrics in fcoe_ctlr_select() The check for conflicting fabrics in fcoe_ctlr_select() ignores any FCFs that aren't usable. This is a minor problem now but becomes more pronounced after later patches. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 4d0be20cb73d..826c260f7951 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -1361,12 +1361,22 @@ static void fcoe_ctlr_select(struct fcoe_ctlr *fip) { struct fcoe_fcf *fcf; struct fcoe_fcf *best = NULL; + struct fcoe_fcf *first; + + first = list_first_entry(&fip->fcfs, struct fcoe_fcf, list); list_for_each_entry(fcf, &fip->fcfs, list) { LIBFCOE_FIP_DBG(fip, "consider FCF for fab %16.16llx " "VFID %d map %x val %d\n", fcf->fabric_name, fcf->vfid, fcf->fc_map, fcoe_ctlr_mtu_valid(fcf)); + if (fcf->fabric_name != first->fabric_name || + fcf->vfid != first->vfid || + fcf->fc_map != first->fc_map) { + LIBFCOE_FIP_DBG(fip, "Conflicting fabric, VFID, " + "or FC-MAP\n"); + return NULL; + } if (!fcoe_ctlr_fcf_usable(fcf)) { LIBFCOE_FIP_DBG(fip, "FCF for fab %16.16llx " "map %x %svalid %savailable\n", @@ -1380,13 +1390,6 @@ static void fcoe_ctlr_select(struct fcoe_ctlr *fip) best = fcf; continue; } - if (fcf->fabric_name != best->fabric_name || - fcf->vfid != best->vfid || - fcf->fc_map != best->fc_map) { - LIBFCOE_FIP_DBG(fip, "Conflicting fabric, VFID, " - "or FC-MAP\n"); - return; - } if (fcf->pri < best->pri) best = fcf; } -- cgit v1.2.3-59-g8ed1b From 794d98e77f5901ceded697f1633463e88f078038 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 30 Nov 2010 16:19:56 -0800 Subject: [SCSI] libfcoe: retry rejected FLOGI to another FCF if possible Switches using multiple-FCFs may reject FLOGI in order to balance the load between multiple FCFs. Even though the FCF was available, it may have more load at the point we actually send the FLOGI. If the FLOGI fails, select a different FCF if possible, among those with the same priority. If no other FCF is available, just deliver the reject to libfc for retry. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 207 +++++++++++++++++++++++++++++++++++++------- include/scsi/libfcoe.h | 8 ++ 2 files changed, 185 insertions(+), 30 deletions(-) diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 826c260f7951..c90622c28b6c 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -54,6 +54,8 @@ MODULE_LICENSE("GPL v2"); static void fcoe_ctlr_timeout(unsigned long); static void fcoe_ctlr_timer_work(struct work_struct *); static void fcoe_ctlr_recv_work(struct work_struct *); +static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *); +static void fcoe_ctlr_select(struct fcoe_ctlr *); static void fcoe_ctlr_vn_start(struct fcoe_ctlr *); static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *, struct sk_buff *); @@ -176,6 +178,7 @@ void fcoe_ctlr_init(struct fcoe_ctlr *fip, enum fip_state mode) fip->mode = mode; INIT_LIST_HEAD(&fip->fcfs); mutex_init(&fip->ctlr_mutex); + spin_lock_init(&fip->ctlr_lock); fip->flogi_oxid = FC_XID_UNKNOWN; setup_timer(&fip->timer, fcoe_ctlr_timeout, (unsigned long)fip); INIT_WORK(&fip->timer_work, fcoe_ctlr_timer_work); @@ -231,17 +234,31 @@ void fcoe_ctlr_destroy(struct fcoe_ctlr *fip) EXPORT_SYMBOL(fcoe_ctlr_destroy); /** - * fcoe_ctlr_announce() - announce new selection + * fcoe_ctlr_announce() - announce new FCF selection * @fip: The FCoE controller * * Also sets the destination MAC for FCoE and control packets + * + * Called with neither ctlr_mutex nor ctlr_lock held. */ static void fcoe_ctlr_announce(struct fcoe_ctlr *fip) { - struct fcoe_fcf *sel = fip->sel_fcf; + struct fcoe_fcf *sel; + struct fcoe_fcf *fcf; + + mutex_lock(&fip->ctlr_mutex); + spin_lock_bh(&fip->ctlr_lock); + + kfree_skb(fip->flogi_req); + fip->flogi_req = NULL; + list_for_each_entry(fcf, &fip->fcfs, list) + fcf->flogi_sent = 0; + + spin_unlock_bh(&fip->ctlr_lock); + sel = fip->sel_fcf; if (sel && !compare_ether_addr(sel->fcf_mac, fip->dest_addr)) - return; + goto unlock; if (!is_zero_ether_addr(fip->dest_addr)) { printk(KERN_NOTICE "libfcoe: host%d: " "FIP Fibre-Channel Forwarder MAC %pM deselected\n", @@ -255,6 +272,8 @@ static void fcoe_ctlr_announce(struct fcoe_ctlr *fip) memcpy(fip->dest_addr, sel->fcf_mac, ETH_ALEN); fip->map_dest = 0; } +unlock: + mutex_unlock(&fip->ctlr_mutex); } /** @@ -591,6 +610,9 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport, * The caller must check that the length is a multiple of 4. * The SKB must have enough headroom (28 bytes) and tailroom (8 bytes). * The the skb must also be an fc_frame. + * + * This is called from the lower-level driver with spinlocks held, + * so we must not take a mutex here. */ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport, struct sk_buff *skb) @@ -628,7 +650,15 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport, switch (op) { case ELS_FLOGI: op = FIP_DT_FLOGI; - break; + if (fip->mode == FIP_MODE_VN2VN) + break; + spin_lock_bh(&fip->ctlr_lock); + kfree_skb(fip->flogi_req); + fip->flogi_req = skb; + fip->flogi_req_send = 1; + spin_unlock_bh(&fip->ctlr_lock); + schedule_work(&fip->timer_work); + return -EINPROGRESS; case ELS_FDISC: if (ntoh24(fh->fh_s_id)) return 0; @@ -1088,18 +1118,24 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) els_op = *(u8 *)(fh + 1); if ((els_dtype == FIP_DT_FLOGI || els_dtype == FIP_DT_FDISC) && - sub == FIP_SC_REP && els_op == ELS_LS_ACC && - fip->mode != FIP_MODE_VN2VN) { - if (!is_valid_ether_addr(granted_mac)) { - LIBFCOE_FIP_DBG(fip, - "Invalid MAC address %pM in FIP ELS\n", - granted_mac); - goto drop; - } - memcpy(fr_cb(fp)->granted_mac, granted_mac, ETH_ALEN); + sub == FIP_SC_REP && fip->mode != FIP_MODE_VN2VN) { + if (els_op == ELS_LS_ACC) { + if (!is_valid_ether_addr(granted_mac)) { + LIBFCOE_FIP_DBG(fip, + "Invalid MAC address %pM in FIP ELS\n", + granted_mac); + goto drop; + } + memcpy(fr_cb(fp)->granted_mac, granted_mac, ETH_ALEN); - if (fip->flogi_oxid == ntohs(fh->fh_ox_id)) - fip->flogi_oxid = FC_XID_UNKNOWN; + if (fip->flogi_oxid == ntohs(fh->fh_ox_id)) { + fip->flogi_oxid = FC_XID_UNKNOWN; + if (els_dtype == FIP_DT_FLOGI) + fcoe_ctlr_announce(fip); + } + } else if (els_dtype == FIP_DT_FLOGI && + !fcoe_ctlr_flogi_retry(fip)) + goto drop; /* retrying FLOGI so drop reject */ } if ((desc_cnt == 0) || ((els_op != ELS_LS_RJT) && @@ -1355,12 +1391,15 @@ drop: * * If there are conflicting advertisements, no FCF can be chosen. * + * If there is already a selected FCF, this will choose a better one or + * an equivalent one that hasn't already been sent a FLOGI. + * * Called with lock held. */ static void fcoe_ctlr_select(struct fcoe_ctlr *fip) { struct fcoe_fcf *fcf; - struct fcoe_fcf *best = NULL; + struct fcoe_fcf *best = fip->sel_fcf; struct fcoe_fcf *first; first = list_first_entry(&fip->fcfs, struct fcoe_fcf, list); @@ -1377,6 +1416,8 @@ static void fcoe_ctlr_select(struct fcoe_ctlr *fip) "or FC-MAP\n"); return NULL; } + if (fcf->flogi_sent) + continue; if (!fcoe_ctlr_fcf_usable(fcf)) { LIBFCOE_FIP_DBG(fip, "FCF for fab %16.16llx " "map %x %svalid %savailable\n", @@ -1386,11 +1427,7 @@ static void fcoe_ctlr_select(struct fcoe_ctlr *fip) "" : "un"); continue; } - if (!best) { - best = fcf; - continue; - } - if (fcf->pri < best->pri) + if (!best || fcf->pri < best->pri || best->flogi_sent) best = fcf; } fip->sel_fcf = best; @@ -1403,6 +1440,121 @@ static void fcoe_ctlr_select(struct fcoe_ctlr *fip) } } +/** + * fcoe_ctlr_flogi_send_locked() - send FIP-encapsulated FLOGI to current FCF + * @fip: The FCoE controller + * + * Returns non-zero error if it could not be sent. + * + * Called with ctlr_mutex and ctlr_lock held. + * Caller must verify that fip->sel_fcf is not NULL. + */ +static int fcoe_ctlr_flogi_send_locked(struct fcoe_ctlr *fip) +{ + struct sk_buff *skb; + struct sk_buff *skb_orig; + struct fc_frame_header *fh; + int error; + + skb_orig = fip->flogi_req; + if (!skb_orig) + return -EINVAL; + + /* + * Clone and send the FLOGI request. If clone fails, use original. + */ + skb = skb_clone(skb_orig, GFP_ATOMIC); + if (!skb) { + skb = skb_orig; + fip->flogi_req = NULL; + } + fh = (struct fc_frame_header *)skb->data; + error = fcoe_ctlr_encaps(fip, fip->lp, FIP_DT_FLOGI, skb, + ntoh24(fh->fh_d_id)); + if (error) { + kfree_skb(skb); + return error; + } + fip->send(fip, skb); + fip->sel_fcf->flogi_sent = 1; + return 0; +} + +/** + * fcoe_ctlr_flogi_retry() - resend FLOGI request to a new FCF if possible + * @fip: The FCoE controller + * + * Returns non-zero error code if there's no FLOGI request to retry or + * no alternate FCF available. + */ +static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *fip) +{ + struct fcoe_fcf *fcf; + int error; + + mutex_lock(&fip->ctlr_mutex); + spin_lock_bh(&fip->ctlr_lock); + LIBFCOE_FIP_DBG(fip, "re-sending FLOGI - reselect\n"); + fcoe_ctlr_select(fip); + fcf = fip->sel_fcf; + if (!fcf || fcf->flogi_sent) { + kfree_skb(fip->flogi_req); + fip->flogi_req = NULL; + error = -ENOENT; + } else { + fcoe_ctlr_solicit(fip, NULL); + error = fcoe_ctlr_flogi_send_locked(fip); + } + spin_unlock_bh(&fip->ctlr_lock); + mutex_unlock(&fip->ctlr_mutex); + return error; +} + + +/** + * fcoe_ctlr_flogi_send() - Handle sending of FIP FLOGI. + * @fip: The FCoE controller that timed out + * + * Done here because fcoe_ctlr_els_send() can't get mutex. + * + * Called with ctlr_mutex held. The caller must not hold ctlr_lock. + */ +static void fcoe_ctlr_flogi_send(struct fcoe_ctlr *fip) +{ + struct fcoe_fcf *fcf; + + spin_lock_bh(&fip->ctlr_lock); + fcf = fip->sel_fcf; + if (!fcf || !fip->flogi_req_send) + goto unlock; + + LIBFCOE_FIP_DBG(fip, "sending FLOGI\n"); + + /* + * If this FLOGI is being sent due to a timeout retry + * to the same FCF as before, select a different FCF if possible. + */ + if (fcf->flogi_sent) { + LIBFCOE_FIP_DBG(fip, "sending FLOGI - reselect\n"); + fcoe_ctlr_select(fip); + fcf = fip->sel_fcf; + if (!fcf || fcf->flogi_sent) { + LIBFCOE_FIP_DBG(fip, "sending FLOGI - clearing\n"); + list_for_each_entry(fcf, &fip->fcfs, list) + fcf->flogi_sent = 0; + fcoe_ctlr_select(fip); + fcf = fip->sel_fcf; + } + } + if (fcf) { + fcoe_ctlr_flogi_send_locked(fip); + fip->flogi_req_send = 0; + } else /* XXX */ + LIBFCOE_FIP_DBG(fip, "No FCF selected - defer send\n"); +unlock: + spin_unlock_bh(&fip->ctlr_lock); +} + /** * fcoe_ctlr_timeout() - FIP timeout handler * @arg: The FCoE controller that timed out @@ -1455,15 +1607,10 @@ static void fcoe_ctlr_timer_work(struct work_struct *work) next_timer = fip->sel_time; } - if (sel != fcf) { - fcf = sel; /* the old FCF may have been freed */ - fcoe_ctlr_announce(fip); - if (sel) { - if (time_after(next_timer, fip->ctlr_ka_time)) - next_timer = fip->ctlr_ka_time; - } else - reset = 1; - } + if (sel && fip->flogi_req_send) + fcoe_ctlr_flogi_send(fip); + else if (!sel && fcf) + reset = 1; if (sel && !sel->fd_flags) { if (time_after_eq(jiffies, fip->ctlr_ka_time)) { diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h index 06f1b5a8ed19..feb6a94c90ea 100644 --- a/include/scsi/libfcoe.h +++ b/include/scsi/libfcoe.h @@ -92,10 +92,12 @@ enum fip_state { * @timer_work: &work_struct for doing keep-alives and resets. * @recv_work: &work_struct for receiving FIP frames. * @fip_recv_list: list of received FIP frames. + * @flogi_req: clone of FLOGI request sent * @rnd_state: state for pseudo-random number generator. * @port_id: proposed or selected local-port ID. * @user_mfs: configured maximum FC frame size, including FC header. * @flogi_oxid: exchange ID of most recent fabric login. + * @flogi_req_send: send of FLOGI requested * @flogi_count: number of FLOGI attempts in AUTO mode. * @map_dest: use the FC_MAP mode for destination MAC addresses. * @spma: supports SPMA server-provided MACs mode @@ -106,6 +108,7 @@ enum fip_state { * @update_mac: LLD-supplied function to handle changes to MAC addresses. * @get_src_addr: LLD-supplied function to supply a source MAC address. * @ctlr_mutex: lock protecting this structure. + * @ctlr_lock: spinlock covering flogi_req * * This structure is used by all FCoE drivers. It contains information * needed by all FCoE low-level drivers (LLDs) as well as internal state @@ -126,12 +129,14 @@ struct fcoe_ctlr { struct work_struct timer_work; struct work_struct recv_work; struct sk_buff_head fip_recv_list; + struct sk_buff *flogi_req; struct rnd_state rnd_state; u32 port_id; u16 user_mfs; u16 flogi_oxid; + u8 flogi_req_send; u8 flogi_count; u8 map_dest; u8 spma; @@ -143,6 +148,7 @@ struct fcoe_ctlr { void (*update_mac)(struct fc_lport *, u8 *addr); u8 * (*get_src_addr)(struct fc_lport *); struct mutex ctlr_mutex; + spinlock_t ctlr_lock; }; /** @@ -155,6 +161,7 @@ struct fcoe_ctlr { * @fcf_mac: Ethernet address of the FCF * @vfid: virtual fabric ID * @pri: selection priority, smaller values are better + * @flogi_sent: current FLOGI sent to this FCF * @flags: flags received from advertisement * @fka_period: keep-alive period, in jiffies * @@ -176,6 +183,7 @@ struct fcoe_fcf { u8 fcf_mac[ETH_ALEN]; u8 pri; + u8 flogi_sent; u16 flags; u32 fka_period; u8 fd_flags:1; -- cgit v1.2.3-59-g8ed1b From 9069f5c433e402be5707f37f3d0dfb376659c1e4 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 30 Nov 2010 16:20:02 -0800 Subject: [SCSI] libfcoe: add debug message for FCF destination MAC When multiple FCFs to the same fabric exist, the debug messages all look alike. Change the message to include the MAC address. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index c90622c28b6c..dcccb0bf3170 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -979,11 +979,9 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) } mtu_valid = fcoe_ctlr_mtu_valid(fcf); fcf->time = jiffies; - if (!found) { - LIBFCOE_FIP_DBG(fip, "New FCF for fab %16.16llx " - "map %x val %d\n", - fcf->fabric_name, fcf->fc_map, mtu_valid); - } + if (!found) + LIBFCOE_FIP_DBG(fip, "New FCF fab %16.16llx mac %pM\n", + fcf->fabric_name, fcf->fcf_mac); /* * If this advertisement is not solicited and our max receive size @@ -1405,10 +1403,12 @@ static void fcoe_ctlr_select(struct fcoe_ctlr *fip) first = list_first_entry(&fip->fcfs, struct fcoe_fcf, list); list_for_each_entry(fcf, &fip->fcfs, list) { - LIBFCOE_FIP_DBG(fip, "consider FCF for fab %16.16llx " - "VFID %d map %x val %d\n", - fcf->fabric_name, fcf->vfid, - fcf->fc_map, fcoe_ctlr_mtu_valid(fcf)); + LIBFCOE_FIP_DBG(fip, "consider FCF fab %16.16llx " + "VFID %d mac %pM map %x val %d " + "sent %u pri %u\n", + fcf->fabric_name, fcf->vfid, fcf->fcf_mac, + fcf->fc_map, fcoe_ctlr_mtu_valid(fcf), + fcf->flogi_sent, fcf->pri); if (fcf->fabric_name != first->fabric_name || fcf->vfid != first->vfid || fcf->fc_map != first->fc_map) { @@ -1432,6 +1432,7 @@ static void fcoe_ctlr_select(struct fcoe_ctlr *fip) } fip->sel_fcf = best; if (best) { + LIBFCOE_FIP_DBG(fip, "using FCF mac %pM\n", best->fcf_mac); fip->port_ka_time = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); fip->ctlr_ka_time = jiffies + best->fka_period; -- cgit v1.2.3-59-g8ed1b From 981c1154b240ee77133a478fcd3853ac18111672 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 30 Nov 2010 16:20:07 -0800 Subject: [SCSI] libfcoe: reorder FCF list to put latest advertiser first When there are several FCFs to choose from, the one most likely to accept a FLOGI on certian switches is the one that last answered a multicast solicit. So, when receiving an advertisement, move the FCF to the front of the list so that it gets chosen first among those with the same priority. Without this, more FLOGIs need to be sent in a test with multiple FCFs and a switch in NPV mode, but it still eventually finds one that accepts the FLOGI. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index dcccb0bf3170..1a0bb230dd03 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -999,6 +999,17 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) if (first && time_after(jiffies, fip->sol_time + sol_tov)) fcoe_ctlr_solicit(fip, NULL); + /* + * Put this FCF at the head of the list for priority among equals. + * This helps in the case of an NPV switch which insists we use + * the FCF that answers multicast solicitations, not the others that + * are sending periodic multicast advertisements. + */ + if (mtu_valid) { + list_del(&fcf->list); + list_add(&fcf->list, &fip->fcfs); + } + /* * If this is the first validated FCF, note the time and * set a timer to trigger selection. -- cgit v1.2.3-59-g8ed1b From ba9cd5d095b42271588c20ccd6ddd561d0e4cc1e Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 30 Nov 2010 16:20:12 -0800 Subject: [SCSI] libfcoe: change fip_select to return new FCF Neaten several calls to fip_select() by having it return the pointer to the new FCF. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 1a0bb230dd03..625c6be25396 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -55,7 +55,6 @@ static void fcoe_ctlr_timeout(unsigned long); static void fcoe_ctlr_timer_work(struct work_struct *); static void fcoe_ctlr_recv_work(struct work_struct *); static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *); -static void fcoe_ctlr_select(struct fcoe_ctlr *); static void fcoe_ctlr_vn_start(struct fcoe_ctlr *); static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *, struct sk_buff *); @@ -1398,6 +1397,8 @@ drop: * fcoe_ctlr_select() - Select the best FCF (if possible) * @fip: The FCoE controller * + * Returns the selected FCF, or NULL if none are usable. + * * If there are conflicting advertisements, no FCF can be chosen. * * If there is already a selected FCF, this will choose a better one or @@ -1405,7 +1406,7 @@ drop: * * Called with lock held. */ -static void fcoe_ctlr_select(struct fcoe_ctlr *fip) +static struct fcoe_fcf *fcoe_ctlr_select(struct fcoe_ctlr *fip) { struct fcoe_fcf *fcf; struct fcoe_fcf *best = fip->sel_fcf; @@ -1450,6 +1451,7 @@ static void fcoe_ctlr_select(struct fcoe_ctlr *fip) if (time_before(fip->ctlr_ka_time, fip->timer.expires)) mod_timer(&fip->timer, fip->ctlr_ka_time); } + return best; } /** @@ -1507,8 +1509,7 @@ static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *fip) mutex_lock(&fip->ctlr_mutex); spin_lock_bh(&fip->ctlr_lock); LIBFCOE_FIP_DBG(fip, "re-sending FLOGI - reselect\n"); - fcoe_ctlr_select(fip); - fcf = fip->sel_fcf; + fcf = fcoe_ctlr_select(fip); if (!fcf || fcf->flogi_sent) { kfree_skb(fip->flogi_req); fip->flogi_req = NULL; @@ -1548,14 +1549,12 @@ static void fcoe_ctlr_flogi_send(struct fcoe_ctlr *fip) */ if (fcf->flogi_sent) { LIBFCOE_FIP_DBG(fip, "sending FLOGI - reselect\n"); - fcoe_ctlr_select(fip); - fcf = fip->sel_fcf; + fcf = fcoe_ctlr_select(fip); if (!fcf || fcf->flogi_sent) { LIBFCOE_FIP_DBG(fip, "sending FLOGI - clearing\n"); list_for_each_entry(fcf, &fip->fcfs, list) fcf->flogi_sent = 0; - fcoe_ctlr_select(fip); - fcf = fip->sel_fcf; + fcf = fcoe_ctlr_select(fip); } } if (fcf) { @@ -1612,8 +1611,7 @@ static void fcoe_ctlr_timer_work(struct work_struct *work) sel = fip->sel_fcf; if (!sel && fip->sel_time) { if (time_after_eq(jiffies, fip->sel_time)) { - fcoe_ctlr_select(fip); - sel = fip->sel_fcf; + sel = fcoe_ctlr_select(fip); fip->sel_time = 0; } else if (time_after(next_timer, fip->sel_time)) next_timer = fip->sel_time; -- cgit v1.2.3-59-g8ed1b From 5f0e385fdafb7d6c8ded6464fa6421c735d96caf Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Tue, 30 Nov 2010 16:20:18 -0800 Subject: [SCSI] libfc: fix statistics for FCP input/output megabytes The statistics for InputMegabytes and OutputMegabytes are misnamed. They're accumulating bytes, not megabytes. The statistic returned via /sys must be in megabytes, however, which is what the HBA-API wants. The FCP code needs to accumulate it in bytes and then divide by 1,000,000 (not 2^20) before it presented via sysfs. This affects fcoe.ko only, not fnic. The fnic driver correctly by accumulating bytes and then converts to megabytes. I checked that libhbalinux is using the /sys file directly without conversion. BTW, qla2xxx does divide by 2^20, which I'm not fixing here. Signed-off-by: Joe Eykholt Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_fcp.c | 4 ++-- drivers/scsi/libfc/fc_lport.c | 8 ++++++-- include/scsi/libfc.h | 8 ++++---- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index a8e0c0acc736..cdc06cda76e5 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -1860,11 +1860,11 @@ static int fc_queuecommand_lck(struct scsi_cmnd *sc_cmd, void (*done)(struct scs if (sc_cmd->sc_data_direction == DMA_FROM_DEVICE) { fsp->req_flags = FC_SRB_READ; stats->InputRequests++; - stats->InputMegabytes += fsp->data_len; + stats->InputBytes += fsp->data_len; } else if (sc_cmd->sc_data_direction == DMA_TO_DEVICE) { fsp->req_flags = FC_SRB_WRITE; stats->OutputRequests++; - stats->OutputMegabytes += fsp->data_len; + stats->OutputBytes += fsp->data_len; } else { fsp->req_flags = 0; stats->ControlRequests++; diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index b91a11e4fa06..c5a10f94f845 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -288,6 +288,8 @@ struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost) struct fc_lport *lport = shost_priv(shost); struct timespec v0, v1; unsigned int cpu; + u64 fcp_in_bytes = 0; + u64 fcp_out_bytes = 0; fcoe_stats = &lport->host_stats; memset(fcoe_stats, 0, sizeof(struct fc_host_statistics)); @@ -310,10 +312,12 @@ struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost) fcoe_stats->fcp_input_requests += stats->InputRequests; fcoe_stats->fcp_output_requests += stats->OutputRequests; fcoe_stats->fcp_control_requests += stats->ControlRequests; - fcoe_stats->fcp_input_megabytes += stats->InputMegabytes; - fcoe_stats->fcp_output_megabytes += stats->OutputMegabytes; + fcp_in_bytes += stats->InputBytes; + fcp_out_bytes += stats->OutputBytes; fcoe_stats->link_failure_count += stats->LinkFailureCount; } + fcoe_stats->fcp_input_megabytes = div_u64(fcp_in_bytes, 1000000); + fcoe_stats->fcp_output_megabytes = div_u64(fcp_out_bytes, 1000000); fcoe_stats->lip_count = -1; fcoe_stats->nos_count = -1; fcoe_stats->loss_of_sync_count = -1; diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 3eb3915eb557..f53c8e31d5fb 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -221,8 +221,8 @@ struct fc_rport_priv { * @InputRequests: Number of input requests * @OutputRequests: Number of output requests * @ControlRequests: Number of control requests - * @InputMegabytes: Number of received megabytes - * @OutputMegabytes: Number of transmitted megabytes + * @InputBytes: Number of received bytes + * @OutputBytes: Number of transmitted bytes * @VLinkFailureCount: Number of virtual link failures * @MissDiscAdvCount: Number of missing FIP discovery advertisement */ @@ -241,8 +241,8 @@ struct fcoe_dev_stats { u64 InputRequests; u64 OutputRequests; u64 ControlRequests; - u64 InputMegabytes; - u64 OutputMegabytes; + u64 InputBytes; + u64 OutputBytes; u64 VLinkFailureCount; u64 MissDiscAdvCount; }; -- cgit v1.2.3-59-g8ed1b From 3e1350c4dc8900476c4db2066c00f13e9e939817 Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Thu, 2 Dec 2010 22:12:03 -0800 Subject: [SCSI] qla4xxx: Drop use of IRQF_DISABLE IRQF_DISABLE flag is deprecated and this flag is a NOOP in kernel. Signed-off-by: Vikas Chaudhary Signed-off-by: Ravi Anand Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_isr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 7c33fd5943d5..5d9575cebff9 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c @@ -1077,7 +1077,7 @@ try_msi: ret = pci_enable_msi(ha->pdev); if (!ret) { ret = request_irq(ha->pdev->irq, qla4_8xxx_msi_handler, - IRQF_DISABLED|IRQF_SHARED, DRIVER_NAME, ha); + IRQF_SHARED, DRIVER_NAME, ha); if (!ret) { DEBUG2(ql4_printk(KERN_INFO, ha, "MSI: Enabled.\n")); set_bit(AF_MSI_ENABLED, &ha->flags); @@ -1095,7 +1095,7 @@ try_msi: try_intx: /* Trying INTx */ ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler, - IRQF_DISABLED|IRQF_SHARED, DRIVER_NAME, ha); + IRQF_SHARED, DRIVER_NAME, ha); if (!ret) { DEBUG2(ql4_printk(KERN_INFO, ha, "INTx: Enabled.\n")); set_bit(AF_INTx_ENABLED, &ha->flags); -- cgit v1.2.3-59-g8ed1b From 61391d314e856030b2b40b5d6ea22b93de0f1fed Mon Sep 17 00:00:00 2001 From: Shyam Sundar Date: Thu, 2 Dec 2010 22:12:08 -0800 Subject: [SCSI] qla4xxx: initialize MSI in correct way IRQF_SHARED flag should not be set when calling request_irq for MSI since this interrupt mechanism cannot be shared like standard INTx Signed-off-by: Vikas Chaudhary Signed-off-by: Shyam Sundar Signed-off-by: Ravi Anand Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_isr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 5d9575cebff9..ca862b12a8db 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c @@ -1077,7 +1077,7 @@ try_msi: ret = pci_enable_msi(ha->pdev); if (!ret) { ret = request_irq(ha->pdev->irq, qla4_8xxx_msi_handler, - IRQF_SHARED, DRIVER_NAME, ha); + 0, DRIVER_NAME, ha); if (!ret) { DEBUG2(ql4_printk(KERN_INFO, ha, "MSI: Enabled.\n")); set_bit(AF_MSI_ENABLED, &ha->flags); -- cgit v1.2.3-59-g8ed1b From a1fc26baae41e00a3ecfd99bbe91aa2435045625 Mon Sep 17 00:00:00 2001 From: Swapnil Nagle Date: Thu, 2 Dec 2010 22:12:15 -0800 Subject: [SCSI] qla4xxx: memory wedge with peg_halt test in loop Signed-off-by: Swapnil Nagle Signed-off-by: Vikas Chaudhary Signed-off-by: Ravi Anand Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_nx.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 474b10d71364..2d95ef20d07d 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c @@ -942,12 +942,55 @@ qla4_8xxx_pinit_from_rom(struct scsi_qla_host *ha, int verbose) /* Halt all the indiviual PEGs and other blocks of the ISP */ qla4_8xxx_rom_lock(ha); + + /* mask all niu interrupts */ + qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x40, 0xff); + /* disable xge rx/tx */ + qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x70000, 0x00); + /* disable xg1 rx/tx */ + qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x80000, 0x00); + + /* halt sre */ + val = qla4_8xxx_rd_32(ha, QLA82XX_CRB_SRE + 0x1000); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_SRE + 0x1000, val & (~(0x1))); + + /* halt epg */ + qla4_8xxx_wr_32(ha, QLA82XX_CRB_EPG + 0x1300, 0x1); + + /* halt timers */ + qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x0, 0x0); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x8, 0x0); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x10, 0x0); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x18, 0x0); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_TIMER + 0x100, 0x0); + + /* halt pegs */ + qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x3c, 1); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_1 + 0x3c, 1); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_2 + 0x3c, 1); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_3 + 0x3c, 1); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_4 + 0x3c, 1); + + /* big hammer */ + msleep(1000); if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) /* don't reset CAM block on reset */ qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xfeffffff); else qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xffffffff); + /* reset ms */ + val = qla4_8xxx_rd_32(ha, QLA82XX_CRB_QDR_NET + 0xe4); + val |= (1 << 1); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_QDR_NET + 0xe4, val); + + msleep(20); + /* unreset ms */ + val = qla4_8xxx_rd_32(ha, QLA82XX_CRB_QDR_NET + 0xe4); + val &= ~(1 << 1); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_QDR_NET + 0xe4, val); + msleep(20); + qla4_8xxx_rom_unlock(ha); /* Read the signature value from the flash. -- cgit v1.2.3-59-g8ed1b From 6790d4fecf4373016e2983f913bcc0f1cdfa8ca0 Mon Sep 17 00:00:00 2001 From: Karen Higgins Date: Thu, 2 Dec 2010 22:12:22 -0800 Subject: [SCSI] qla4xxx: use correct fw_ddb_index in abort task Signed-off-by: Vikas Chaudhary Signed-off-by: Karen Higgins Signed-off-by: Ravi Anand Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_def.h | 3 +-- drivers/scsi/qla4xxx/ql4_mbx.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 0f3bfc3da5cf..060e64f57a3d 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -175,7 +175,7 @@ struct srb { struct list_head list; /* (8) */ struct scsi_qla_host *ha; /* HA the SP is queued on */ - struct ddb_entry *ddb; + struct ddb_entry *ddb; uint16_t flags; /* (1) Status flags. */ #define SRB_DMA_VALID BIT_3 /* DMA Buffer mapped. */ @@ -191,7 +191,6 @@ struct srb { struct scsi_cmnd *cmd; /* (4) SCSI command block */ dma_addr_t dma_handle; /* (4) for unmap of single transfers */ struct kref srb_ref; /* reference count for this srb */ - uint32_t fw_ddb_index; uint8_t err_id; /* error id */ #define SRB_ERR_PORT 1 /* Request failed because "port down" */ #define SRB_ERR_LOOP 2 /* Request failed because "loop down" */ diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 2d2f9c879bfd..8961d4c03e3b 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -934,7 +934,7 @@ int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb) return status; mbox_cmd[0] = MBOX_CMD_ABORT_TASK; - mbox_cmd[1] = srb->fw_ddb_index; + mbox_cmd[1] = srb->ddb->fw_ddb_index; mbox_cmd[2] = index; /* Immediate Command Enable */ mbox_cmd[5] = 0x01; -- cgit v1.2.3-59-g8ed1b From e6b07df8b0f1530a8ed606f6f464487520d74ad9 Mon Sep 17 00:00:00 2001 From: Lalit Chandivade Date: Thu, 2 Dec 2010 22:12:27 -0800 Subject: [SCSI] qla4xxx: do not process interrupt unconditionally in mailbox command do not process interrupt unconditionally, process interrupt only in polling mode Signed-off-by: Vikas Chaudhary Signed-off-by: Lalit Chandivade Signed-off-by: Ravi Anand Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_mbx.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 8961d4c03e3b..b7e43b1d2a70 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -81,23 +81,7 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, */ spin_lock_irqsave(&ha->hardware_lock, flags); - if (is_qla8022(ha)) { - intr_status = readl(&ha->qla4_8xxx_reg->host_int); - if (intr_status & ISRX_82XX_RISC_INT) { - /* Service existing interrupt */ - DEBUG2(printk("scsi%ld: %s: " - "servicing existing interrupt\n", - ha->host_no, __func__)); - intr_status = readl(&ha->qla4_8xxx_reg->host_status); - ha->isp_ops->interrupt_service_routine(ha, intr_status); - clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags); - if (test_bit(AF_INTERRUPTS_ON, &ha->flags) && - test_bit(AF_INTx_ENABLED, &ha->flags)) - qla4_8xxx_wr_32(ha, - ha->nx_legacy_intr.tgt_mask_reg, - 0xfbff); - } - } else { + if (!is_qla8022(ha)) { intr_status = readl(&ha->reg->ctrl_status); if (intr_status & CSR_SCSI_PROCESSOR_INTR) { /* Service existing interrupt */ -- cgit v1.2.3-59-g8ed1b From fe998527e3f1f5a6eeab5baa23ac2b60ae47e96b Mon Sep 17 00:00:00 2001 From: Lalit Chandivade Date: Thu, 2 Dec 2010 22:12:36 -0800 Subject: [SCSI] qla4xxx: put device in FAILED state for 82XX initialization failure Signed-off-by: Vikas Chaudhary Signed-off-by: Lalit Chandivade Signed-off-by: Ravi Anand Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_os.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 0d48fb4d1044..fa5ddadf4869 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -1721,6 +1721,14 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, if (!test_bit(AF_ONLINE, &ha->flags)) { ql4_printk(KERN_WARNING, ha, "Failed to initialize adapter\n"); + if (is_qla8022(ha) && ql4xdontresethba) { + /* Put the device in failed state. */ + DEBUG2(printk(KERN_ERR "HW STATE: FAILED\n")); + qla4_8xxx_idc_lock(ha); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, + QLA82XX_DEV_FAILED); + qla4_8xxx_idc_unlock(ha); + } ret = -ENODEV; goto probe_failed; } -- cgit v1.2.3-59-g8ed1b From 4cd83cbef878b5d0d4c65ac0a20d12a8bf9f551d Mon Sep 17 00:00:00 2001 From: Lalit Chandivade Date: Thu, 2 Dec 2010 22:12:40 -0800 Subject: [SCSI] qla4xxx: Fail initialization if qla4_8xxx_pci_mem_write_2M fails Since if fw load is failing, running on incomplete fw load would be fatal. Signed-off-by: Vikas Chaudhary Signed-off-by: Lalit Chandivade Signed-off-by: Ravi Anand Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_nx.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 2d95ef20d07d..18b0ad67a273 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c @@ -1127,14 +1127,14 @@ qla4_8xxx_pinit_from_rom(struct scsi_qla_host *ha, int verbose) static int qla4_8xxx_load_from_flash(struct scsi_qla_host *ha, uint32_t image_start) { - int i; + int i, rval = 0; long size = 0; long flashaddr, memaddr; u64 data; u32 high, low; flashaddr = memaddr = ha->hw.flt_region_bootload; - size = (image_start - flashaddr)/8; + size = (image_start - flashaddr) / 8; DEBUG2(printk("scsi%ld: %s: bootldr=0x%lx, fw_image=0x%x\n", ha->host_no, __func__, flashaddr, image_start)); @@ -1143,14 +1143,18 @@ qla4_8xxx_load_from_flash(struct scsi_qla_host *ha, uint32_t image_start) if ((qla4_8xxx_rom_fast_read(ha, flashaddr, (int *)&low)) || (qla4_8xxx_rom_fast_read(ha, flashaddr + 4, (int *)&high))) { - return -1; + rval = -1; + goto exit_load_from_flash; } data = ((u64)high << 32) | low ; - qla4_8xxx_pci_mem_write_2M(ha, memaddr, &data, 8); + rval = qla4_8xxx_pci_mem_write_2M(ha, memaddr, &data, 8); + if (rval) + goto exit_load_from_flash; + flashaddr += 8; memaddr += 8; - if (i%0x1000 == 0) + if (i % 0x1000 == 0) msleep(1); } @@ -1162,7 +1166,8 @@ qla4_8xxx_load_from_flash(struct scsi_qla_host *ha, uint32_t image_start) qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0x80001e); read_unlock(&ha->hw_lock); - return 0; +exit_load_from_flash: + return rval; } static int qla4_8xxx_load_fw(struct scsi_qla_host *ha, uint32_t image_start) -- cgit v1.2.3-59-g8ed1b From e128271b7bcb9c8955cadbf2e18f8af288979e6b Mon Sep 17 00:00:00 2001 From: Prasanna Mumbai Date: Thu, 2 Dec 2010 22:12:43 -0800 Subject: [SCSI] qla4xxx: cache new IP address acquired via DHCP Prior to firmware state change from ACQUIRING to READY, an 0x8029 AEN is received. Added code to check previous state being ACQUIRING in order to update the ip address in the driver. Signed-off-by: Vikas Chaudhary Signed-off-by: Prasanna Mumbai Signed-off-by: Ravi Anand Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_isr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index ca862b12a8db..90a217ff3a3f 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c @@ -554,7 +554,8 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, /* mbox_sts[2] = Old ACB state * mbox_sts[3] = new ACB state */ if ((mbox_sts[3] == ACB_STATE_VALID) && - (mbox_sts[2] == ACB_STATE_TENTATIVE)) + ((mbox_sts[2] == ACB_STATE_TENTATIVE) || + (mbox_sts[2] == ACB_STATE_ACQUIRING))) set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags); else if ((mbox_sts[3] == ACB_STATE_ACQUIRING) && (mbox_sts[2] == ACB_STATE_VALID)) -- cgit v1.2.3-59-g8ed1b From d56a1f7b39631806ee3d49445a65da6288b099b4 Mon Sep 17 00:00:00 2001 From: Lalit Chandivade Date: Thu, 2 Dec 2010 22:12:45 -0800 Subject: [SCSI] qla4xxx: do not check for fw hung if reset retry is in progress Signed-off-by: Vikas Chaudhary Signed-off-by: Lalit Chandivade Signed-off-by: Ravi Anand Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_os.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index fa5ddadf4869..a1ba085565af 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -706,7 +706,9 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha) dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); /* don't poll if reset is going on */ - if (!test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags)) { + if (!(test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) || + test_bit(DPC_RESET_HA, &ha->dpc_flags) || + test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags))) { if (dev_state == QLA82XX_DEV_NEED_RESET && !test_bit(DPC_RESET_HA, &ha->dpc_flags)) { printk("scsi%ld: %s: HW State: NEED RESET!\n", -- cgit v1.2.3-59-g8ed1b From 3930b8c1f3582d43757cbcc9b7ecaf05f6b4a66e Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Thu, 2 Dec 2010 22:12:47 -0800 Subject: [SCSI] qla4xxx: do not reset hba if ql4xdontresethba is set Signed-off-by: Vikas Chaudhary Signed-off-by: Ravi Anand Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_os.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index a1ba085565af..3cb74c9269a4 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -711,15 +711,17 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha) test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags))) { if (dev_state == QLA82XX_DEV_NEED_RESET && !test_bit(DPC_RESET_HA, &ha->dpc_flags)) { - printk("scsi%ld: %s: HW State: NEED RESET!\n", - ha->host_no, __func__); - set_bit(DPC_RESET_HA, &ha->dpc_flags); - qla4xxx_wake_dpc(ha); - qla4xxx_mailbox_premature_completion(ha); + if (!ql4xdontresethba) { + ql4_printk(KERN_INFO, ha, "%s: HW State: " + "NEED RESET!\n", __func__); + set_bit(DPC_RESET_HA, &ha->dpc_flags); + qla4xxx_wake_dpc(ha); + qla4xxx_mailbox_premature_completion(ha); + } } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT && !test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) { - printk("scsi%ld: %s: HW State: NEED QUIES!\n", - ha->host_no, __func__); + ql4_printk(KERN_INFO, ha, "%s: HW State: NEED QUIES!\n", + __func__); set_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags); qla4xxx_wake_dpc(ha); } else { -- cgit v1.2.3-59-g8ed1b From 7d01d0698f450ed8cc9fd4557f88a3309c868d44 Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Thu, 2 Dec 2010 22:12:51 -0800 Subject: [SCSI] qla4xxx: Updated the Copyright header Signed-off-by: Vikas Chaudhary Signed-off-by: Ravi Anand Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_dbg.c | 2 +- drivers/scsi/qla4xxx/ql4_dbg.h | 2 +- drivers/scsi/qla4xxx/ql4_def.h | 2 +- drivers/scsi/qla4xxx/ql4_fw.h | 2 +- drivers/scsi/qla4xxx/ql4_glbl.h | 2 +- drivers/scsi/qla4xxx/ql4_init.c | 2 +- drivers/scsi/qla4xxx/ql4_inline.h | 2 +- drivers/scsi/qla4xxx/ql4_iocb.c | 2 +- drivers/scsi/qla4xxx/ql4_isr.c | 2 +- drivers/scsi/qla4xxx/ql4_mbx.c | 2 +- drivers/scsi/qla4xxx/ql4_nvram.c | 2 +- drivers/scsi/qla4xxx/ql4_nvram.h | 2 +- drivers/scsi/qla4xxx/ql4_nx.c | 2 +- drivers/scsi/qla4xxx/ql4_nx.h | 6 +++--- drivers/scsi/qla4xxx/ql4_os.c | 2 +- drivers/scsi/qla4xxx/ql4_version.h | 2 +- 16 files changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/qla4xxx/ql4_dbg.c b/drivers/scsi/qla4xxx/ql4_dbg.c index edcf048215dd..af62c3cf8752 100644 --- a/drivers/scsi/qla4xxx/ql4_dbg.c +++ b/drivers/scsi/qla4xxx/ql4_dbg.c @@ -1,6 +1,6 @@ /* * QLogic iSCSI HBA Driver - * Copyright (c) 2003-2006 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla4xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla4xxx/ql4_dbg.h b/drivers/scsi/qla4xxx/ql4_dbg.h index d861c3b411c8..abd83602cdda 100644 --- a/drivers/scsi/qla4xxx/ql4_dbg.h +++ b/drivers/scsi/qla4xxx/ql4_dbg.h @@ -1,6 +1,6 @@ /* * QLogic iSCSI HBA Driver - * Copyright (c) 2003-2006 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla4xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 060e64f57a3d..2fc0045b1a52 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -1,6 +1,6 @@ /* * QLogic iSCSI HBA Driver - * Copyright (c) 2003-2006 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla4xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index 5e757d7fff7d..c1985792f034 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h @@ -1,6 +1,6 @@ /* * QLogic iSCSI HBA Driver - * Copyright (c) 2003-2006 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla4xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index 6575a47501e5..8fad99b7eef4 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h @@ -1,6 +1,6 @@ /* * QLogic iSCSI HBA Driver - * Copyright (c) 2003-2006 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla4xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index dc01fa3da5d1..1629c48c35ef 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -1,6 +1,6 @@ /* * QLogic iSCSI HBA Driver - * Copyright (c) 2003-2006 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla4xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla4xxx/ql4_inline.h b/drivers/scsi/qla4xxx/ql4_inline.h index 9471ac755000..62f90bdec5d5 100644 --- a/drivers/scsi/qla4xxx/ql4_inline.h +++ b/drivers/scsi/qla4xxx/ql4_inline.h @@ -1,6 +1,6 @@ /* * QLogic iSCSI HBA Driver - * Copyright (c) 2003-2006 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla4xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c index 5ae49fd87846..75fcd82a8fca 100644 --- a/drivers/scsi/qla4xxx/ql4_iocb.c +++ b/drivers/scsi/qla4xxx/ql4_iocb.c @@ -1,6 +1,6 @@ /* * QLogic iSCSI HBA Driver - * Copyright (c) 2003-2006 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla4xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 90a217ff3a3f..6ffbe9727dff 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c @@ -1,6 +1,6 @@ /* * QLogic iSCSI HBA Driver - * Copyright (c) 2003-2006 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla4xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index b7e43b1d2a70..f65626aec7c1 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -1,6 +1,6 @@ /* * QLogic iSCSI HBA Driver - * Copyright (c) 2003-2006 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla4xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla4xxx/ql4_nvram.c b/drivers/scsi/qla4xxx/ql4_nvram.c index f0d0fbf88aa2..b4b859b2d47e 100644 --- a/drivers/scsi/qla4xxx/ql4_nvram.c +++ b/drivers/scsi/qla4xxx/ql4_nvram.c @@ -1,6 +1,6 @@ /* * QLogic iSCSI HBA Driver - * Copyright (c) 2003-2006 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla4xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla4xxx/ql4_nvram.h b/drivers/scsi/qla4xxx/ql4_nvram.h index 7a8fc66a760d..b3831bd29479 100644 --- a/drivers/scsi/qla4xxx/ql4_nvram.h +++ b/drivers/scsi/qla4xxx/ql4_nvram.h @@ -1,6 +1,6 @@ /* * QLogic iSCSI HBA Driver - * Copyright (c) 2003-2006 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla4xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 18b0ad67a273..3d5ef2df4134 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c @@ -1,6 +1,6 @@ /* * QLogic iSCSI HBA Driver - * Copyright (c) 2003-2009 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla4xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla4xxx/ql4_nx.h b/drivers/scsi/qla4xxx/ql4_nx.h index ff689bf53007..35376a1c3f1b 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.h +++ b/drivers/scsi/qla4xxx/ql4_nx.h @@ -1,8 +1,8 @@ /* - * QLogic Fibre Channel HBA Driver - * Copyright (c) 2003-2008 QLogic Corporation + * QLogic iSCSI HBA Driver + * Copyright (c) 2003-2010 QLogic Corporation * - * See LICENSE.qla2xxx for copyright and licensing details. + * See LICENSE.qla4xxx for copyright and licensing details. */ #ifndef __QLA_NX_H #define __QLA_NX_H diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 3cb74c9269a4..3fc1d256636f 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -1,6 +1,6 @@ /* * QLogic iSCSI HBA Driver - * Copyright (c) 2003-2006 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla4xxx for copyright and licensing details. */ diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index 9bfacf4ed137..454d3f5eb270 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h @@ -1,6 +1,6 @@ /* * QLogic iSCSI HBA Driver - * Copyright (c) 2003-2006 QLogic Corporation + * Copyright (c) 2003-2010 QLogic Corporation * * See LICENSE.qla4xxx for copyright and licensing details. */ -- cgit v1.2.3-59-g8ed1b From 6b57b159709dcb4d53e64738f2d1f73b36e41601 Mon Sep 17 00:00:00 2001 From: Vikas Chaudhary Date: Thu, 2 Dec 2010 22:13:00 -0800 Subject: [SCSI] qla4xxx: Update driver version to 5.02.00-k5 Signed-off-by: Vikas Chaudhary Signed-off-by: Ravi Anand Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index 454d3f5eb270..8475b308e01b 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h @@ -5,4 +5,4 @@ * See LICENSE.qla4xxx for copyright and licensing details. */ -#define QLA4XXX_DRIVER_VERSION "5.02.00-k4" +#define QLA4XXX_DRIVER_VERSION "5.02.00-k5" -- cgit v1.2.3-59-g8ed1b From ae0904f60fab7cb20c48d32eefdd735e478b91fb Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Thu, 2 Dec 2010 15:16:12 +0100 Subject: [SCSI] zfcp: Redesign of the debug tracing for recovery actions. The tracing environment of the zfcp LLD has become very bulky and hard to maintain. Small changes involve a large modification process which is error-prone and not effective. This patch is the first of a set to redesign the zfcp tracing to a more straight-forward and easy to extend scheme. It removes all interpretation and visualization parts and focuses on bare logging of the information. This patch deals with all trace records of the zfcp error recovery. Signed-off-by: Swen schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_dbf.c | 281 ++++++++++--------------------------------- drivers/s390/scsi/zfcp_dbf.h | 100 ++++++++------- drivers/s390/scsi/zfcp_erp.c | 31 ++--- drivers/s390/scsi/zfcp_ext.h | 12 +- 4 files changed, 139 insertions(+), 285 deletions(-) diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 2cdd6b28ff7f..675503628cc9 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -50,11 +50,6 @@ static void zfcp_dbf_tag(char **p, const char *label, const char *tag) *p += sprintf(*p, "\n"); } -static void zfcp_dbf_outs(char **buf, const char *s1, const char *s2) -{ - *buf += sprintf(*buf, "%-24s%s\n", s1, s2); -} - static void zfcp_dbf_out(char **buf, const char *s, const char *format, ...) { va_list arg; @@ -439,241 +434,96 @@ static struct debug_view zfcp_dbf_hba_view = { .format_proc = zfcp_dbf_hba_view_format, }; -static const char *zfcp_dbf_rec_tags[] = { - [ZFCP_REC_DBF_ID_THREAD] = "thread", - [ZFCP_REC_DBF_ID_TARGET] = "target", - [ZFCP_REC_DBF_ID_TRIGGER] = "trigger", - [ZFCP_REC_DBF_ID_ACTION] = "action", -}; - -static int zfcp_dbf_rec_view_format(debug_info_t *id, struct debug_view *view, - char *buf, const char *_rec) +static void zfcp_dbf_set_common(struct zfcp_dbf_rec *rec, + struct zfcp_adapter *adapter, + struct zfcp_port *port, + struct scsi_device *sdev) { - struct zfcp_dbf_rec_record *r = (struct zfcp_dbf_rec_record *)_rec; - char *p = buf; - char hint[ZFCP_DBF_ID_SIZE + 1]; - - memcpy(hint, r->id2, ZFCP_DBF_ID_SIZE); - hint[ZFCP_DBF_ID_SIZE] = 0; - zfcp_dbf_outs(&p, "tag", zfcp_dbf_rec_tags[r->id]); - zfcp_dbf_outs(&p, "hint", hint); - switch (r->id) { - case ZFCP_REC_DBF_ID_THREAD: - zfcp_dbf_out(&p, "total", "%d", r->u.thread.total); - zfcp_dbf_out(&p, "ready", "%d", r->u.thread.ready); - zfcp_dbf_out(&p, "running", "%d", r->u.thread.running); - break; - case ZFCP_REC_DBF_ID_TARGET: - zfcp_dbf_out(&p, "reference", "0x%016Lx", r->u.target.ref); - zfcp_dbf_out(&p, "status", "0x%08x", r->u.target.status); - zfcp_dbf_out(&p, "erp_count", "%d", r->u.target.erp_count); - zfcp_dbf_out(&p, "d_id", "0x%06x", r->u.target.d_id); - zfcp_dbf_out(&p, "wwpn", "0x%016Lx", r->u.target.wwpn); - zfcp_dbf_out(&p, "fcp_lun", "0x%016Lx", r->u.target.fcp_lun); - break; - case ZFCP_REC_DBF_ID_TRIGGER: - zfcp_dbf_out(&p, "reference", "0x%016Lx", r->u.trigger.ref); - zfcp_dbf_out(&p, "erp_action", "0x%016Lx", r->u.trigger.action); - zfcp_dbf_out(&p, "requested", "%d", r->u.trigger.want); - zfcp_dbf_out(&p, "executed", "%d", r->u.trigger.need); - zfcp_dbf_out(&p, "wwpn", "0x%016Lx", r->u.trigger.wwpn); - zfcp_dbf_out(&p, "fcp_lun", "0x%016Lx", r->u.trigger.fcp_lun); - zfcp_dbf_out(&p, "adapter_status", "0x%08x", r->u.trigger.as); - zfcp_dbf_out(&p, "port_status", "0x%08x", r->u.trigger.ps); - zfcp_dbf_out(&p, "lun_status", "0x%08x", r->u.trigger.ls); - break; - case ZFCP_REC_DBF_ID_ACTION: - zfcp_dbf_out(&p, "erp_action", "0x%016Lx", r->u.action.action); - zfcp_dbf_out(&p, "fsf_req", "0x%016Lx", r->u.action.fsf_req); - zfcp_dbf_out(&p, "status", "0x%08Lx", r->u.action.status); - zfcp_dbf_out(&p, "step", "0x%08Lx", r->u.action.step); - break; + rec->adapter_status = atomic_read(&adapter->status); + if (port) { + rec->port_status = atomic_read(&port->status); + rec->wwpn = port->wwpn; + rec->d_id = port->d_id; + } + if (sdev) { + rec->lun_status = atomic_read(&sdev_to_zfcp(sdev)->status); + rec->lun = zfcp_scsi_dev_lun(sdev); } - p += sprintf(p, "\n"); - return p - buf; } -static struct debug_view zfcp_dbf_rec_view = { - .name = "structured", - .header_proc = zfcp_dbf_view_header, - .format_proc = zfcp_dbf_rec_view_format, -}; - /** - * zfcp_dbf_rec_thread - trace event related to recovery thread operation - * @id2: identifier for event - * @dbf: reference to dbf structure - * This function assumes that the caller is holding erp_lock. + * zfcp_dbf_rec_trig - trace event related to triggered recovery + * @tag: identifier for event + * @adapter: adapter on which the erp_action should run + * @port: remote port involved in the erp_action + * @sdev: scsi device involved in the erp_action + * @want: wanted erp_action + * @need: required erp_action + * + * The adapter->erp_lock has to be held. */ -void zfcp_dbf_rec_thread(char *id2, struct zfcp_dbf *dbf) +void zfcp_dbf_rec_trig(char *tag, struct zfcp_adapter *adapter, + struct zfcp_port *port, struct scsi_device *sdev, + u8 want, u8 need) { - struct zfcp_adapter *adapter = dbf->adapter; - struct zfcp_dbf_rec_record *r = &dbf->rec_buf; - unsigned long flags = 0; + struct zfcp_dbf *dbf = adapter->dbf; + struct zfcp_dbf_rec *rec = &dbf->rec_buf; struct list_head *entry; - unsigned ready = 0, running = 0, total; - - list_for_each(entry, &adapter->erp_ready_head) - ready++; - list_for_each(entry, &adapter->erp_running_head) - running++; - total = adapter->erp_total_count; - - spin_lock_irqsave(&dbf->rec_lock, flags); - memset(r, 0, sizeof(*r)); - r->id = ZFCP_REC_DBF_ID_THREAD; - memcpy(r->id2, id2, ZFCP_DBF_ID_SIZE); - r->u.thread.total = total; - r->u.thread.ready = ready; - r->u.thread.running = running; - debug_event(dbf->rec, 6, r, sizeof(*r)); - spin_unlock_irqrestore(&dbf->rec_lock, flags); -} - -/** - * zfcp_dbf_rec_thread - trace event related to recovery thread operation - * @id2: identifier for event - * @adapter: adapter - * This function assumes that the caller does not hold erp_lock. - */ -void zfcp_dbf_rec_thread_lock(char *id2, struct zfcp_dbf *dbf) -{ - struct zfcp_adapter *adapter = dbf->adapter; - unsigned long flags; - - read_lock_irqsave(&adapter->erp_lock, flags); - zfcp_dbf_rec_thread(id2, dbf); - read_unlock_irqrestore(&adapter->erp_lock, flags); -} - -static void zfcp_dbf_rec_target(char *id2, void *ref, struct zfcp_dbf *dbf, - atomic_t *status, atomic_t *erp_count, u64 wwpn, - u32 d_id, u64 fcp_lun) -{ - struct zfcp_dbf_rec_record *r = &dbf->rec_buf; unsigned long flags; spin_lock_irqsave(&dbf->rec_lock, flags); - memset(r, 0, sizeof(*r)); - r->id = ZFCP_REC_DBF_ID_TARGET; - memcpy(r->id2, id2, ZFCP_DBF_ID_SIZE); - r->u.target.ref = (unsigned long)ref; - r->u.target.status = atomic_read(status); - r->u.target.wwpn = wwpn; - r->u.target.d_id = d_id; - r->u.target.fcp_lun = fcp_lun; - r->u.target.erp_count = atomic_read(erp_count); - debug_event(dbf->rec, 3, r, sizeof(*r)); - spin_unlock_irqrestore(&dbf->rec_lock, flags); -} - -/** - * zfcp_dbf_rec_adapter - trace event for adapter state change - * @id: identifier for trigger of state change - * @ref: additional reference (e.g. request) - * @dbf: reference to dbf structure - */ -void zfcp_dbf_rec_adapter(char *id, void *ref, struct zfcp_dbf *dbf) -{ - struct zfcp_adapter *adapter = dbf->adapter; + memset(rec, 0, sizeof(*rec)); - zfcp_dbf_rec_target(id, ref, dbf, &adapter->status, - &adapter->erp_counter, 0, 0, - ZFCP_DBF_INVALID_LUN); -} + rec->id = ZFCP_DBF_REC_TRIG; + memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); + zfcp_dbf_set_common(rec, adapter, port, sdev); -/** - * zfcp_dbf_rec_port - trace event for port state change - * @id: identifier for trigger of state change - * @ref: additional reference (e.g. request) - * @port: port - */ -void zfcp_dbf_rec_port(char *id, void *ref, struct zfcp_port *port) -{ - struct zfcp_dbf *dbf = port->adapter->dbf; + list_for_each(entry, &adapter->erp_ready_head) + rec->u.trig.ready++; - zfcp_dbf_rec_target(id, ref, dbf, &port->status, - &port->erp_counter, port->wwpn, port->d_id, - ZFCP_DBF_INVALID_LUN); -} + list_for_each(entry, &adapter->erp_running_head) + rec->u.trig.running++; -/** - * zfcp_dbf_rec_lun - trace event for LUN state change - * @id: identifier for trigger of state change - * @ref: additional reference (e.g. request) - * @sdev: SCSI device - */ -void zfcp_dbf_rec_lun(char *id, void *ref, struct scsi_device *sdev) -{ - struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); - struct zfcp_port *port = zfcp_sdev->port; - struct zfcp_dbf *dbf = port->adapter->dbf; + rec->u.trig.want = want; + rec->u.trig.need = need; - zfcp_dbf_rec_target(id, ref, dbf, &zfcp_sdev->status, - &zfcp_sdev->erp_counter, port->wwpn, port->d_id, - zfcp_scsi_dev_lun(sdev)); + debug_event(dbf->rec, 1, rec, sizeof(*rec)); + spin_unlock_irqrestore(&dbf->rec_lock, flags); } + /** - * zfcp_dbf_rec_trigger - trace event for triggered error recovery - * @id2: identifier for error recovery trigger - * @ref: additional reference (e.g. request) - * @want: originally requested error recovery action - * @need: error recovery action actually initiated - * @action: address of error recovery action struct - * @adapter: adapter - * @port: port - * @sdev: SCSI device + * zfcp_dbf_rec_run - trace event related to running recovery + * @tag: identifier for event + * @erp: erp_action running */ -void zfcp_dbf_rec_trigger(char *id2, void *ref, u8 want, u8 need, void *action, - struct zfcp_adapter *adapter, struct zfcp_port *port, - struct scsi_device *sdev) +void zfcp_dbf_rec_run(char *tag, struct zfcp_erp_action *erp) { - struct zfcp_dbf *dbf = adapter->dbf; - struct zfcp_dbf_rec_record *r = &dbf->rec_buf; + struct zfcp_dbf *dbf = erp->adapter->dbf; + struct zfcp_dbf_rec *rec = &dbf->rec_buf; unsigned long flags; spin_lock_irqsave(&dbf->rec_lock, flags); - memset(r, 0, sizeof(*r)); - r->id = ZFCP_REC_DBF_ID_TRIGGER; - memcpy(r->id2, id2, ZFCP_DBF_ID_SIZE); - r->u.trigger.ref = (unsigned long)ref; - r->u.trigger.want = want; - r->u.trigger.need = need; - r->u.trigger.action = (unsigned long)action; - r->u.trigger.as = atomic_read(&adapter->status); - if (port) { - r->u.trigger.ps = atomic_read(&port->status); - r->u.trigger.wwpn = port->wwpn; - } - if (sdev) - r->u.trigger.ls = atomic_read(&sdev_to_zfcp(sdev)->status); - r->u.trigger.fcp_lun = sdev ? zfcp_scsi_dev_lun(sdev) : - ZFCP_DBF_INVALID_LUN; - debug_event(dbf->rec, action ? 1 : 4, r, sizeof(*r)); - spin_unlock_irqrestore(&dbf->rec_lock, flags); -} + memset(rec, 0, sizeof(*rec)); -/** - * zfcp_dbf_rec_action - trace event showing progress of recovery action - * @id2: identifier - * @erp_action: error recovery action struct pointer - */ -void zfcp_dbf_rec_action(char *id2, struct zfcp_erp_action *erp_action) -{ - struct zfcp_dbf *dbf = erp_action->adapter->dbf; - struct zfcp_dbf_rec_record *r = &dbf->rec_buf; - unsigned long flags; + rec->id = ZFCP_DBF_REC_RUN; + memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); + zfcp_dbf_set_common(rec, erp->adapter, erp->port, erp->sdev); - spin_lock_irqsave(&dbf->rec_lock, flags); - memset(r, 0, sizeof(*r)); - r->id = ZFCP_REC_DBF_ID_ACTION; - memcpy(r->id2, id2, ZFCP_DBF_ID_SIZE); - r->u.action.action = (unsigned long)erp_action; - r->u.action.status = erp_action->status; - r->u.action.step = erp_action->step; - r->u.action.fsf_req = erp_action->fsf_req_id; - debug_event(dbf->rec, 5, r, sizeof(*r)); + rec->u.run.fsf_req_id = erp->fsf_req_id; + rec->u.run.rec_status = erp->status; + rec->u.run.rec_step = erp->step; + rec->u.run.rec_action = erp->action; + + if (erp->sdev) + rec->u.run.rec_count = + atomic_read(&sdev_to_zfcp(erp->sdev)->erp_counter); + else if (erp->port) + rec->u.run.rec_count = atomic_read(&erp->port->erp_counter); + else + rec->u.run.rec_count = atomic_read(&erp->adapter->erp_counter); + + debug_event(dbf->rec, 1, rec, sizeof(*rec)); spin_unlock_irqrestore(&dbf->rec_lock, flags); } @@ -1019,8 +869,7 @@ int zfcp_dbf_adapter_register(struct zfcp_adapter *adapter) /* debug feature area which records recovery activity */ sprintf(dbf_name, "zfcp_%s_rec", dev_name(&adapter->ccw_device->dev)); - dbf->rec = zfcp_dbf_reg(dbf_name, 3, &zfcp_dbf_rec_view, - sizeof(struct zfcp_dbf_rec_record)); + dbf->rec = zfcp_dbf_reg(dbf_name, 3, NULL, sizeof(struct zfcp_dbf_rec)); if (!dbf->rec) goto err_out; diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h index 04081b1b62b4..2e823d4ede6e 100644 --- a/drivers/s390/scsi/zfcp_dbf.h +++ b/drivers/s390/scsi/zfcp_dbf.h @@ -27,6 +27,7 @@ #include "zfcp_fsf.h" #include "zfcp_def.h" +#define ZFCP_DBF_TAG_LEN 7 #define ZFCP_DBF_TAG_SIZE 4 #define ZFCP_DBF_ID_SIZE 7 @@ -40,57 +41,72 @@ struct zfcp_dbf_dump { u8 data[]; /* dump data */ } __attribute__ ((packed)); -struct zfcp_dbf_rec_record_thread { - u32 total; +/** + * struct zfcp_dbf_rec_trigger - trace record for triggered recovery action + * @ready: number of ready recovery actions + * @running: number of running recovery actions + * @want: wanted recovery action + * @need: needed recovery action + */ +struct zfcp_dbf_rec_trigger { u32 ready; u32 running; -}; - -struct zfcp_dbf_rec_record_target { - u64 ref; - u32 status; - u32 d_id; - u64 wwpn; - u64 fcp_lun; - u32 erp_count; -}; - -struct zfcp_dbf_rec_record_trigger { u8 want; u8 need; - u32 as; - u32 ps; - u32 ls; - u64 ref; - u64 action; - u64 wwpn; - u64 fcp_lun; -}; +} __packed; + +/** + * struct zfcp_dbf_rec_running - trace record for running recovery + * @fsf_req_id: request id for fsf requests + * @rec_status: status of the fsf request + * @rec_step: current step of the recovery action + * rec_count: recovery counter + */ +struct zfcp_dbf_rec_running { + u64 fsf_req_id; + u32 rec_status; + u16 rec_step; + u8 rec_action; + u8 rec_count; +} __packed; -struct zfcp_dbf_rec_record_action { - u32 status; - u32 step; - u64 action; - u64 fsf_req; +/** + * enum zfcp_dbf_rec_id - recovery trace record id + * @ZFCP_DBF_REC_TRIG: triggered recovery identifier + * @ZFCP_DBF_REC_RUN: running recovery identifier + */ +enum zfcp_dbf_rec_id { + ZFCP_DBF_REC_TRIG = 1, + ZFCP_DBF_REC_RUN = 2, }; -struct zfcp_dbf_rec_record { +/** + * struct zfcp_dbf_rec - trace record for error recovery actions + * @id: unique number of recovery record type + * @tag: identifier string specifying the location of initiation + * @lun: logical unit number + * @wwpn: word wide port number + * @d_id: destination ID + * @adapter_status: current status of the adapter + * @port_status: current status of the port + * @lun_status: current status of the lun + * @u.trig: structure zfcp_dbf_rec_trigger + * @u.run: structure zfcp_dbf_rec_running + */ +struct zfcp_dbf_rec { u8 id; - char id2[7]; + char tag[ZFCP_DBF_TAG_LEN]; + u64 lun; + u64 wwpn; + u32 d_id; + u32 adapter_status; + u32 port_status; + u32 lun_status; union { - struct zfcp_dbf_rec_record_action action; - struct zfcp_dbf_rec_record_thread thread; - struct zfcp_dbf_rec_record_target target; - struct zfcp_dbf_rec_record_trigger trigger; + struct zfcp_dbf_rec_trigger trig; + struct zfcp_dbf_rec_running run; } u; -}; - -enum { - ZFCP_REC_DBF_ID_ACTION, - ZFCP_REC_DBF_ID_THREAD, - ZFCP_REC_DBF_ID_TARGET, - ZFCP_REC_DBF_ID_TRIGGER, -}; +} __packed; struct zfcp_dbf_hba_record_response { u32 fsf_command; @@ -232,7 +248,7 @@ struct zfcp_dbf { spinlock_t hba_lock; spinlock_t san_lock; spinlock_t scsi_lock; - struct zfcp_dbf_rec_record rec_buf; + struct zfcp_dbf_rec rec_buf; struct zfcp_dbf_hba_record hba_buf; struct zfcp_dbf_san_record san_buf; struct zfcp_dbf_scsi_record scsi_buf; diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 0bcd5806bd9a..62b1b4a03ee3 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -76,9 +76,9 @@ static void zfcp_erp_action_ready(struct zfcp_erp_action *act) struct zfcp_adapter *adapter = act->adapter; list_move(&act->list, &act->adapter->erp_ready_head); - zfcp_dbf_rec_action("erardy1", act); + zfcp_dbf_rec_run("erardy1", act); wake_up(&adapter->erp_ready_wq); - zfcp_dbf_rec_thread("erardy2", adapter->dbf); + zfcp_dbf_rec_run("erardy2", act); } static void zfcp_erp_action_dismiss(struct zfcp_erp_action *act) @@ -239,7 +239,7 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, char *id, void *ref, u32 act_status) { int retval = 1, need; - struct zfcp_erp_action *act = NULL; + struct zfcp_erp_action *act; if (!adapter->erp_thread) return -EIO; @@ -255,10 +255,9 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, ++adapter->erp_total_count; list_add_tail(&act->list, &adapter->erp_ready_head); wake_up(&adapter->erp_ready_wq); - zfcp_dbf_rec_thread("eracte1", adapter->dbf); retval = 0; out: - zfcp_dbf_rec_trigger(id, ref, want, need, act, adapter, port, sdev); + zfcp_dbf_rec_trig(id, adapter, port, sdev, want, need); return retval; } @@ -490,14 +489,14 @@ static int status_change_set(unsigned long mask, atomic_t *status) static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter) { if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status)) - zfcp_dbf_rec_adapter("eraubl1", NULL, adapter->dbf); + zfcp_dbf_rec_run("eraubl1", &adapter->erp_action); atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status); } static void zfcp_erp_port_unblock(struct zfcp_port *port) { if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status)) - zfcp_dbf_rec_port("erpubl1", NULL, port); + zfcp_dbf_rec_run("erpubl1", &port->erp_action); atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status); } @@ -506,14 +505,14 @@ static void zfcp_erp_lun_unblock(struct scsi_device *sdev) struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status)) - zfcp_dbf_rec_lun("erlubl1", NULL, sdev); + zfcp_dbf_rec_run("erlubl1", &sdev_to_zfcp(sdev)->erp_action); atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status); } static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action) { list_move(&erp_action->list, &erp_action->adapter->erp_running_head); - zfcp_dbf_rec_action("erator1", erp_action); + zfcp_dbf_rec_run("erator1", erp_action); } static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act) @@ -530,11 +529,11 @@ static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act) if (act->status & (ZFCP_STATUS_ERP_DISMISSED | ZFCP_STATUS_ERP_TIMEDOUT)) { req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; - zfcp_dbf_rec_action("erscf_1", act); + zfcp_dbf_rec_run("erscf_1", act); req->erp_action = NULL; } if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) - zfcp_dbf_rec_action("erscf_2", act); + zfcp_dbf_rec_run("erscf_2", act); if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) act->fsf_req_id = 0; } else @@ -693,10 +692,8 @@ static int zfcp_erp_adapter_strat_fsf_xconf(struct zfcp_erp_action *erp_action) return ZFCP_ERP_FAILED; } - zfcp_dbf_rec_thread_lock("erasfx1", adapter->dbf); wait_event(adapter->erp_ready_wq, !list_empty(&adapter->erp_ready_head)); - zfcp_dbf_rec_thread_lock("erasfx2", adapter->dbf); if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) break; @@ -735,10 +732,10 @@ static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *act) if (ret) return ZFCP_ERP_FAILED; - zfcp_dbf_rec_thread_lock("erasox1", adapter->dbf); + zfcp_dbf_rec_run("erasox1", act); wait_event(adapter->erp_ready_wq, !list_empty(&adapter->erp_ready_head)); - zfcp_dbf_rec_thread_lock("erasox2", adapter->dbf); + zfcp_dbf_rec_run("erasox2", act); if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) return ZFCP_ERP_FAILED; @@ -1206,7 +1203,7 @@ static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action) } list_del(&erp_action->list); - zfcp_dbf_rec_action("eractd1", erp_action); + zfcp_dbf_rec_run("eractd1", erp_action); switch (erp_action->action) { case ZFCP_ERP_ACTION_REOPEN_LUN: @@ -1357,11 +1354,9 @@ static int zfcp_erp_thread(void *data) unsigned long flags; for (;;) { - zfcp_dbf_rec_thread_lock("erthrd1", adapter->dbf); wait_event_interruptible(adapter->erp_ready_wq, !list_empty(&adapter->erp_ready_head) || kthread_should_stop()); - zfcp_dbf_rec_thread_lock("erthrd2", adapter->dbf); if (kthread_should_stop()) break; diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index bf8f3e514839..2d6ee75dfe34 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -46,15 +46,9 @@ extern void zfcp_cfdc_adapter_access_changed(struct zfcp_adapter *); /* zfcp_dbf.c */ extern int zfcp_dbf_adapter_register(struct zfcp_adapter *); extern void zfcp_dbf_adapter_unregister(struct zfcp_dbf *); -extern void zfcp_dbf_rec_thread(char *, struct zfcp_dbf *); -extern void zfcp_dbf_rec_thread_lock(char *, struct zfcp_dbf *); -extern void zfcp_dbf_rec_adapter(char *, void *, struct zfcp_dbf *); -extern void zfcp_dbf_rec_port(char *, void *, struct zfcp_port *); -extern void zfcp_dbf_rec_lun(char *, void *, struct scsi_device *); -extern void zfcp_dbf_rec_trigger(char *, void *, u8, u8, void *, - struct zfcp_adapter *, struct zfcp_port *, - struct scsi_device *); -extern void zfcp_dbf_rec_action(char *, struct zfcp_erp_action *); +extern void zfcp_dbf_rec_trig(char *, struct zfcp_adapter *, + struct zfcp_port *, struct scsi_device *, u8, u8); +extern void zfcp_dbf_rec_run(char *, struct zfcp_erp_action *); extern void _zfcp_dbf_hba_fsf_response(const char *, int, struct zfcp_fsf_req *, struct zfcp_dbf *); extern void _zfcp_dbf_hba_fsf_unsol(const char *, int level, struct zfcp_dbf *, -- cgit v1.2.3-59-g8ed1b From 2c55b750a884b86dea8b4cc5f15e1484cc47a25c Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Thu, 2 Dec 2010 15:16:13 +0100 Subject: [SCSI] zfcp: Redesign of the debug tracing for SAN records. This patch is the continuation to redesign the zfcp tracing to a more straight-forward and easy to extend scheme. This patch deals with all trace records of the zfcp SAN area. Signed-off-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_dbf.c | 201 +++++++++++-------------------------------- drivers/s390/scsi/zfcp_dbf.h | 68 +++++++-------- drivers/s390/scsi/zfcp_ext.h | 8 +- drivers/s390/scsi/zfcp_fc.c | 2 +- drivers/s390/scsi/zfcp_fsf.c | 8 +- 5 files changed, 85 insertions(+), 202 deletions(-) diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 675503628cc9..6ece47e5148c 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -527,183 +527,79 @@ void zfcp_dbf_rec_run(char *tag, struct zfcp_erp_action *erp) spin_unlock_irqrestore(&dbf->rec_lock, flags); } -/** - * zfcp_dbf_san_ct_request - trace event for issued CT request - * @fsf_req: request containing issued CT data - * @d_id: destination id where ct request is sent to - */ -void zfcp_dbf_san_ct_request(struct zfcp_fsf_req *fsf_req, u32 d_id) -{ - struct zfcp_fsf_ct_els *ct = (struct zfcp_fsf_ct_els *)fsf_req->data; - struct zfcp_adapter *adapter = fsf_req->adapter; - struct zfcp_dbf *dbf = adapter->dbf; - struct fc_ct_hdr *hdr = sg_virt(ct->req); - struct zfcp_dbf_san_record *r = &dbf->san_buf; - struct zfcp_dbf_san_record_ct_request *oct = &r->u.ct_req; - int level = 3; - unsigned long flags; - - spin_lock_irqsave(&dbf->san_lock, flags); - memset(r, 0, sizeof(*r)); - strncpy(r->tag, "octc", ZFCP_DBF_TAG_SIZE); - r->fsf_reqid = fsf_req->req_id; - r->fsf_seqno = fsf_req->seq_no; - oct->d_id = d_id; - oct->cmd_req_code = hdr->ct_cmd; - oct->revision = hdr->ct_rev; - oct->gs_type = hdr->ct_fs_type; - oct->gs_subtype = hdr->ct_fs_subtype; - oct->options = hdr->ct_options; - oct->max_res_size = hdr->ct_mr_size; - oct->len = min((int)ct->req->length - (int)sizeof(struct fc_ct_hdr), - ZFCP_DBF_SAN_MAX_PAYLOAD); - debug_event(dbf->san, level, r, sizeof(*r)); - zfcp_dbf_hexdump(dbf->san, r, sizeof(*r), level, - (void *)hdr + sizeof(struct fc_ct_hdr), oct->len); - spin_unlock_irqrestore(&dbf->san_lock, flags); -} - -/** - * zfcp_dbf_san_ct_response - trace event for completion of CT request - * @fsf_req: request containing CT response - */ -void zfcp_dbf_san_ct_response(struct zfcp_fsf_req *fsf_req) +static inline +void zfcp_dbf_san(char *tag, struct zfcp_dbf *dbf, void *data, u8 id, u16 len, + u64 req_id, u32 d_id) { - struct zfcp_fsf_ct_els *ct = (struct zfcp_fsf_ct_els *)fsf_req->data; - struct zfcp_adapter *adapter = fsf_req->adapter; - struct fc_ct_hdr *hdr = sg_virt(ct->resp); - struct zfcp_dbf *dbf = adapter->dbf; - struct zfcp_dbf_san_record *r = &dbf->san_buf; - struct zfcp_dbf_san_record_ct_response *rct = &r->u.ct_resp; - int level = 3; + struct zfcp_dbf_san *rec = &dbf->san_buf; + u16 rec_len; unsigned long flags; spin_lock_irqsave(&dbf->san_lock, flags); - memset(r, 0, sizeof(*r)); - strncpy(r->tag, "rctc", ZFCP_DBF_TAG_SIZE); - r->fsf_reqid = fsf_req->req_id; - r->fsf_seqno = fsf_req->seq_no; - rct->cmd_rsp_code = hdr->ct_cmd; - rct->revision = hdr->ct_rev; - rct->reason_code = hdr->ct_reason; - rct->expl = hdr->ct_explan; - rct->vendor_unique = hdr->ct_vendor; - rct->max_res_size = hdr->ct_mr_size; - rct->len = min((int)ct->resp->length - (int)sizeof(struct fc_ct_hdr), - ZFCP_DBF_SAN_MAX_PAYLOAD); - debug_event(dbf->san, level, r, sizeof(*r)); - zfcp_dbf_hexdump(dbf->san, r, sizeof(*r), level, - (void *)hdr + sizeof(struct fc_ct_hdr), rct->len); - spin_unlock_irqrestore(&dbf->san_lock, flags); -} + memset(rec, 0, sizeof(*rec)); -static void zfcp_dbf_san_els(const char *tag, int level, - struct zfcp_fsf_req *fsf_req, u32 d_id, - void *buffer, int buflen) -{ - struct zfcp_adapter *adapter = fsf_req->adapter; - struct zfcp_dbf *dbf = adapter->dbf; - struct zfcp_dbf_san_record *rec = &dbf->san_buf; - unsigned long flags; + rec->id = id; + rec->fsf_req_id = req_id; + rec->d_id = d_id; + rec_len = min(len, (u16)ZFCP_DBF_SAN_MAX_PAYLOAD); + memcpy(rec->payload, data, rec_len); + memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); - spin_lock_irqsave(&dbf->san_lock, flags); - memset(rec, 0, sizeof(*rec)); - strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE); - rec->fsf_reqid = fsf_req->req_id; - rec->fsf_seqno = fsf_req->seq_no; - rec->u.els.d_id = d_id; - debug_event(dbf->san, level, rec, sizeof(*rec)); - zfcp_dbf_hexdump(dbf->san, rec, sizeof(*rec), level, - buffer, min(buflen, ZFCP_DBF_SAN_MAX_PAYLOAD)); + debug_event(dbf->san, 1, rec, sizeof(*rec)); spin_unlock_irqrestore(&dbf->san_lock, flags); } /** - * zfcp_dbf_san_els_request - trace event for issued ELS - * @fsf_req: request containing issued ELS + * zfcp_dbf_san_req - trace event for issued SAN request + * @tag: indentifier for event + * @fsf_req: request containing issued CT data + * d_id: destination ID */ -void zfcp_dbf_san_els_request(struct zfcp_fsf_req *fsf_req) +void zfcp_dbf_san_req(char *tag, struct zfcp_fsf_req *fsf, u32 d_id) { - struct zfcp_fsf_ct_els *els = (struct zfcp_fsf_ct_els *)fsf_req->data; - u32 d_id = ntoh24(fsf_req->qtcb->bottom.support.d_id); + struct zfcp_dbf *dbf = fsf->adapter->dbf; + struct zfcp_fsf_ct_els *ct_els = fsf->data; + u16 length; - zfcp_dbf_san_els("oels", 2, fsf_req, d_id, - sg_virt(els->req), els->req->length); + length = (u16)(ct_els->req->length + FC_CT_HDR_LEN); + zfcp_dbf_san(tag, dbf, sg_virt(ct_els->req), ZFCP_DBF_SAN_REQ, length, + fsf->req_id, d_id); } /** - * zfcp_dbf_san_els_response - trace event for completed ELS - * @fsf_req: request containing ELS response + * zfcp_dbf_san_res - trace event for received SAN request + * @tag: indentifier for event + * @fsf_req: request containing issued CT data */ -void zfcp_dbf_san_els_response(struct zfcp_fsf_req *fsf_req) +void zfcp_dbf_san_res(char *tag, struct zfcp_fsf_req *fsf) { - struct zfcp_fsf_ct_els *els = (struct zfcp_fsf_ct_els *)fsf_req->data; - u32 d_id = ntoh24(fsf_req->qtcb->bottom.support.d_id); + struct zfcp_dbf *dbf = fsf->adapter->dbf; + struct zfcp_fsf_ct_els *ct_els = fsf->data; + u16 length; - zfcp_dbf_san_els("rels", 2, fsf_req, d_id, - sg_virt(els->resp), els->resp->length); + length = (u16)(ct_els->resp->length + FC_CT_HDR_LEN); + zfcp_dbf_san(tag, dbf, sg_virt(ct_els->resp), ZFCP_DBF_SAN_RES, length, + fsf->req_id, 0); } /** - * zfcp_dbf_san_incoming_els - trace event for incomig ELS - * @fsf_req: request containing unsolicited status buffer with incoming ELS + * zfcp_dbf_san_in_els - trace event for incoming ELS + * @tag: indentifier for event + * @fsf_req: request containing issued CT data */ -void zfcp_dbf_san_incoming_els(struct zfcp_fsf_req *fsf_req) -{ - struct fsf_status_read_buffer *buf = - (struct fsf_status_read_buffer *)fsf_req->data; - int length = (int)buf->length - - (int)((void *)&buf->payload - (void *)buf); - - zfcp_dbf_san_els("iels", 1, fsf_req, ntoh24(buf->d_id), - (void *)buf->payload.data, length); -} - -static int zfcp_dbf_san_view_format(debug_info_t *id, struct debug_view *view, - char *out_buf, const char *in_buf) +void zfcp_dbf_san_in_els(char *tag, struct zfcp_fsf_req *fsf) { - struct zfcp_dbf_san_record *r = (struct zfcp_dbf_san_record *)in_buf; - char *p = out_buf; - - if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0) - return 0; - - zfcp_dbf_tag(&p, "tag", r->tag); - zfcp_dbf_out(&p, "fsf_reqid", "0x%0Lx", r->fsf_reqid); - zfcp_dbf_out(&p, "fsf_seqno", "0x%08x", r->fsf_seqno); - - if (strncmp(r->tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) { - struct zfcp_dbf_san_record_ct_request *ct = &r->u.ct_req; - zfcp_dbf_out(&p, "d_id", "0x%06x", ct->d_id); - zfcp_dbf_out(&p, "cmd_req_code", "0x%04x", ct->cmd_req_code); - zfcp_dbf_out(&p, "revision", "0x%02x", ct->revision); - zfcp_dbf_out(&p, "gs_type", "0x%02x", ct->gs_type); - zfcp_dbf_out(&p, "gs_subtype", "0x%02x", ct->gs_subtype); - zfcp_dbf_out(&p, "options", "0x%02x", ct->options); - zfcp_dbf_out(&p, "max_res_size", "0x%04x", ct->max_res_size); - } else if (strncmp(r->tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) { - struct zfcp_dbf_san_record_ct_response *ct = &r->u.ct_resp; - zfcp_dbf_out(&p, "cmd_rsp_code", "0x%04x", ct->cmd_rsp_code); - zfcp_dbf_out(&p, "revision", "0x%02x", ct->revision); - zfcp_dbf_out(&p, "reason_code", "0x%02x", ct->reason_code); - zfcp_dbf_out(&p, "reason_code_expl", "0x%02x", ct->expl); - zfcp_dbf_out(&p, "vendor_unique", "0x%02x", ct->vendor_unique); - zfcp_dbf_out(&p, "max_res_size", "0x%04x", ct->max_res_size); - } else if (strncmp(r->tag, "oels", ZFCP_DBF_TAG_SIZE) == 0 || - strncmp(r->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 || - strncmp(r->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) { - struct zfcp_dbf_san_record_els *els = &r->u.els; - zfcp_dbf_out(&p, "d_id", "0x%06x", els->d_id); - } - return p - out_buf; + struct zfcp_dbf *dbf = fsf->adapter->dbf; + struct fsf_status_read_buffer *srb = + (struct fsf_status_read_buffer *) fsf->data; + u16 length; + + length = (u16)(srb->length - + offsetof(struct fsf_status_read_buffer, payload)); + zfcp_dbf_san(tag, dbf, srb->payload.data, ZFCP_DBF_SAN_ELS, length, + fsf->req_id, ntoh24(srb->d_id)); } -static struct debug_view zfcp_dbf_san_view = { - .name = "structured", - .header_proc = zfcp_dbf_view_header, - .format_proc = zfcp_dbf_san_view_format, -}; - void _zfcp_dbf_scsi(const char *tag, const char *tag2, int level, struct zfcp_dbf *dbf, struct scsi_cmnd *scsi_cmnd, struct zfcp_fsf_req *fsf_req, unsigned long old_req_id) @@ -882,8 +778,7 @@ int zfcp_dbf_adapter_register(struct zfcp_adapter *adapter) /* debug feature area which records SAN command failures and recovery */ sprintf(dbf_name, "zfcp_%s_san", dev_name(&adapter->ccw_device->dev)); - dbf->san = zfcp_dbf_reg(dbf_name, 6, &zfcp_dbf_san_view, - sizeof(struct zfcp_dbf_san_record)); + dbf->san = zfcp_dbf_reg(dbf_name, 3, NULL, sizeof(struct zfcp_dbf_san)); if (!dbf->san) goto err_out; diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h index 2e823d4ede6e..a3af6bd3d5aa 100644 --- a/drivers/s390/scsi/zfcp_dbf.h +++ b/drivers/s390/scsi/zfcp_dbf.h @@ -108,6 +108,34 @@ struct zfcp_dbf_rec { } u; } __packed; +/** + * enum zfcp_dbf_san_id - SAN trace record identifier + * @ZFCP_DBF_SAN_REQ: request trace record id + * @ZFCP_DBF_SAN_RES: response trace record id + * @ZFCP_DBF_SAN_ELS: extended link service record id + */ +enum zfcp_dbf_san_id { + ZFCP_DBF_SAN_REQ = 1, + ZFCP_DBF_SAN_RES = 2, + ZFCP_DBF_SAN_ELS = 3, +}; + +/** struct zfcp_dbf_san - trace record for SAN requests and responses + * @id: unique number of recovery record type + * @tag: identifier string specifying the location of initiation + * @fsf_req_id: request id for fsf requests + * @payload: unformatted information related to request/response + * @d_id: destination id + */ +struct zfcp_dbf_san { + u8 id; + char tag[ZFCP_DBF_TAG_LEN]; + u64 fsf_req_id; + u32 d_id; +#define ZFCP_DBF_SAN_MAX_PAYLOAD (FC_CT_HDR_LEN + 32) + char payload[ZFCP_DBF_SAN_MAX_PAYLOAD]; +} __packed; + struct zfcp_dbf_hba_record_response { u32 fsf_command; u64 fsf_reqid; @@ -176,44 +204,6 @@ struct zfcp_dbf_hba_record { } u; } __attribute__ ((packed)); -struct zfcp_dbf_san_record_ct_request { - u16 cmd_req_code; - u8 revision; - u8 gs_type; - u8 gs_subtype; - u8 options; - u16 max_res_size; - u32 len; - u32 d_id; -} __attribute__ ((packed)); - -struct zfcp_dbf_san_record_ct_response { - u16 cmd_rsp_code; - u8 revision; - u8 reason_code; - u8 expl; - u8 vendor_unique; - u16 max_res_size; - u32 len; -} __attribute__ ((packed)); - -struct zfcp_dbf_san_record_els { - u32 d_id; -} __attribute__ ((packed)); - -struct zfcp_dbf_san_record { - u8 tag[ZFCP_DBF_TAG_SIZE]; - u64 fsf_reqid; - u32 fsf_seqno; - union { - struct zfcp_dbf_san_record_ct_request ct_req; - struct zfcp_dbf_san_record_ct_response ct_resp; - struct zfcp_dbf_san_record_els els; - } u; -} __attribute__ ((packed)); - -#define ZFCP_DBF_SAN_MAX_PAYLOAD 1024 - struct zfcp_dbf_scsi_record { u8 tag[ZFCP_DBF_TAG_SIZE]; u8 tag2[ZFCP_DBF_TAG_SIZE]; @@ -250,7 +240,7 @@ struct zfcp_dbf { spinlock_t scsi_lock; struct zfcp_dbf_rec rec_buf; struct zfcp_dbf_hba_record hba_buf; - struct zfcp_dbf_san_record san_buf; + struct zfcp_dbf_san san_buf; struct zfcp_dbf_scsi_record scsi_buf; struct zfcp_adapter *adapter; }; diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 2d6ee75dfe34..ff7effe55379 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -55,11 +55,9 @@ extern void _zfcp_dbf_hba_fsf_unsol(const char *, int level, struct zfcp_dbf *, struct fsf_status_read_buffer *); extern void zfcp_dbf_hba_qdio(struct zfcp_dbf *, unsigned int, int, int); extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *); -extern void zfcp_dbf_san_ct_request(struct zfcp_fsf_req *, u32); -extern void zfcp_dbf_san_ct_response(struct zfcp_fsf_req *); -extern void zfcp_dbf_san_els_request(struct zfcp_fsf_req *); -extern void zfcp_dbf_san_els_response(struct zfcp_fsf_req *); -extern void zfcp_dbf_san_incoming_els(struct zfcp_fsf_req *); +extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32); +extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *); +extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *); extern void _zfcp_dbf_scsi(const char *, const char *, int, struct zfcp_dbf *, struct scsi_cmnd *, struct zfcp_fsf_req *, unsigned long); diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 86fd905df48b..7d44d9c59bdc 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -251,7 +251,7 @@ void zfcp_fc_incoming_els(struct zfcp_fsf_req *fsf_req) (struct fsf_status_read_buffer *) fsf_req->data; unsigned int els_type = status_buffer->payload.data[0]; - zfcp_dbf_san_incoming_els(fsf_req); + zfcp_dbf_san_in_els("fciels1", fsf_req); if (els_type == ELS_PLOGI) zfcp_fc_incoming_plogi(fsf_req); else if (els_type == ELS_LOGO) diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 2eb7dd56ab80..6d805c50627f 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -882,7 +882,7 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req) switch (header->fsf_status) { case FSF_GOOD: - zfcp_dbf_san_ct_response(req); + zfcp_dbf_san_res("fsscth1", req); ct->status = 0; break; case FSF_SERVICE_CLASS_NOT_SUPPORTED: @@ -1025,7 +1025,7 @@ int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port, req->qtcb->header.port_handle = wka_port->handle; req->data = ct; - zfcp_dbf_san_ct_request(req, wka_port->d_id); + zfcp_dbf_san_req("fssct_1", req, wka_port->d_id); ret = zfcp_fsf_req_send(req); if (ret) @@ -1053,7 +1053,7 @@ static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req) switch (header->fsf_status) { case FSF_GOOD: - zfcp_dbf_san_els_response(req); + zfcp_dbf_san_res("fsselh1", req); send_els->status = 0; break; case FSF_SERVICE_CLASS_NOT_SUPPORTED: @@ -1127,7 +1127,7 @@ int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id, req->handler = zfcp_fsf_send_els_handler; req->data = els; - zfcp_dbf_san_els_request(req); + zfcp_dbf_san_req("fssels1", req, d_id); ret = zfcp_fsf_req_send(req); if (ret) -- cgit v1.2.3-59-g8ed1b From a54ca0f62f953898b05549391ac2a8a4dad6482b Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Thu, 2 Dec 2010 15:16:14 +0100 Subject: [SCSI] zfcp: Redesign of the debug tracing for HBA records. This patch is the continuation to redesign the zfcp tracing to a more straight-forward and easy to extend scheme. This patch deals with all trace records of the zfcp HBA area. Signed-off-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_dbf.c | 433 ++++++++++++------------------------------ drivers/s390/scsi/zfcp_dbf.h | 197 +++++++++---------- drivers/s390/scsi/zfcp_ext.h | 10 +- drivers/s390/scsi/zfcp_fsf.c | 18 +- drivers/s390/scsi/zfcp_qdio.c | 2 - 5 files changed, 229 insertions(+), 431 deletions(-) diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 6ece47e5148c..b57a47b64b80 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -22,22 +22,34 @@ module_param(dbfsize, uint, 0400); MODULE_PARM_DESC(dbfsize, "number of pages for each debug feature area (default 4)"); -static void zfcp_dbf_hexdump(debug_info_t *dbf, void *to, int to_len, - int level, char *from, int from_len) +static inline unsigned int zfcp_dbf_plen(unsigned int offset) { - int offset; - struct zfcp_dbf_dump *dump = to; - int room = to_len - sizeof(*dump); - - for (offset = 0; offset < from_len; offset += dump->size) { - memset(to, 0, to_len); - strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE); - dump->total_size = from_len; - dump->offset = offset; - dump->size = min(from_len - offset, room); - memcpy(dump->data, from + offset, dump->size); - debug_event(dbf, level, dump, dump->size + sizeof(*dump)); + return sizeof(struct zfcp_dbf_pay) + offset - ZFCP_DBF_PAY_MAX_REC; +} + +static inline +void zfcp_dbf_pl_write(struct zfcp_dbf *dbf, void *data, u16 length, char *area, + u64 req_id) +{ + struct zfcp_dbf_pay *pl = &dbf->pay_buf; + u16 offset = 0, rec_length; + + spin_lock(&dbf->pay_lock); + memset(pl, 0, sizeof(*pl)); + pl->fsf_req_id = req_id; + memcpy(pl->area, area, ZFCP_DBF_TAG_LEN); + + while (offset < length) { + rec_length = min((u16) ZFCP_DBF_PAY_MAX_REC, + (u16) (length - offset)); + memcpy(pl->data, data + offset, rec_length); + debug_event(dbf->pay, 1, pl, zfcp_dbf_plen(rec_length)); + + offset += rec_length; + pl->counter++; } + + spin_unlock(&dbf->pay_lock); } static void zfcp_dbf_tag(char **p, const char *label, const char *tag) @@ -104,336 +116,117 @@ static int zfcp_dbf_view_header(debug_info_t *id, struct debug_view *view, return p - out_buf; } -void _zfcp_dbf_hba_fsf_response(const char *tag2, int level, - struct zfcp_fsf_req *fsf_req, - struct zfcp_dbf *dbf) -{ - struct fsf_qtcb *qtcb = fsf_req->qtcb; - union fsf_prot_status_qual *prot_status_qual = - &qtcb->prefix.prot_status_qual; - union fsf_status_qual *fsf_status_qual = &qtcb->header.fsf_status_qual; - struct scsi_cmnd *scsi_cmnd; - struct zfcp_port *port; - struct zfcp_unit *unit; - struct zfcp_send_els *send_els; - struct zfcp_dbf_hba_record *rec = &dbf->hba_buf; - struct zfcp_dbf_hba_record_response *response = &rec->u.response; - unsigned long flags; - - spin_lock_irqsave(&dbf->hba_lock, flags); - memset(rec, 0, sizeof(*rec)); - strncpy(rec->tag, "resp", ZFCP_DBF_TAG_SIZE); - strncpy(rec->tag2, tag2, ZFCP_DBF_TAG_SIZE); - - response->fsf_command = fsf_req->fsf_command; - response->fsf_reqid = fsf_req->req_id; - response->fsf_seqno = fsf_req->seq_no; - response->fsf_issued = fsf_req->issued; - response->fsf_prot_status = qtcb->prefix.prot_status; - response->fsf_status = qtcb->header.fsf_status; - memcpy(response->fsf_prot_status_qual, - prot_status_qual, FSF_PROT_STATUS_QUAL_SIZE); - memcpy(response->fsf_status_qual, - fsf_status_qual, FSF_STATUS_QUALIFIER_SIZE); - response->fsf_req_status = fsf_req->status; - response->sbal_first = fsf_req->qdio_req.sbal_first; - response->sbal_last = fsf_req->qdio_req.sbal_last; - response->sbal_response = fsf_req->qdio_req.sbal_response; - response->pool = fsf_req->pool != NULL; - response->erp_action = (unsigned long)fsf_req->erp_action; - - switch (fsf_req->fsf_command) { - case FSF_QTCB_FCP_CMND: - if (fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT) - break; - scsi_cmnd = (struct scsi_cmnd *)fsf_req->data; - if (scsi_cmnd) { - response->u.fcp.cmnd = (unsigned long)scsi_cmnd; - response->u.fcp.data_dir = - qtcb->bottom.io.data_direction; - } - break; - - case FSF_QTCB_OPEN_PORT_WITH_DID: - case FSF_QTCB_CLOSE_PORT: - case FSF_QTCB_CLOSE_PHYSICAL_PORT: - port = (struct zfcp_port *)fsf_req->data; - response->u.port.wwpn = port->wwpn; - response->u.port.d_id = port->d_id; - response->u.port.port_handle = qtcb->header.port_handle; - break; - - case FSF_QTCB_OPEN_LUN: - case FSF_QTCB_CLOSE_LUN: - unit = (struct zfcp_unit *)fsf_req->data; - port = unit->port; - response->u.unit.wwpn = port->wwpn; - response->u.unit.fcp_lun = unit->fcp_lun; - response->u.unit.port_handle = qtcb->header.port_handle; - response->u.unit.lun_handle = qtcb->header.lun_handle; - break; - - case FSF_QTCB_SEND_ELS: - send_els = (struct zfcp_send_els *)fsf_req->data; - response->u.els.d_id = ntoh24(qtcb->bottom.support.d_id); - break; - - case FSF_QTCB_ABORT_FCP_CMND: - case FSF_QTCB_SEND_GENERIC: - case FSF_QTCB_EXCHANGE_CONFIG_DATA: - case FSF_QTCB_EXCHANGE_PORT_DATA: - case FSF_QTCB_DOWNLOAD_CONTROL_FILE: - case FSF_QTCB_UPLOAD_CONTROL_FILE: - break; - } - - debug_event(dbf->hba, level, rec, sizeof(*rec)); - - /* have fcp channel microcode fixed to use as little as possible */ - if (fsf_req->fsf_command != FSF_QTCB_FCP_CMND) { - /* adjust length skipping trailing zeros */ - char *buf = (char *)qtcb + qtcb->header.log_start; - int len = qtcb->header.log_length; - for (; len && !buf[len - 1]; len--); - zfcp_dbf_hexdump(dbf->hba, rec, sizeof(*rec), level, buf, - len); - } - - spin_unlock_irqrestore(&dbf->hba_lock, flags); -} - -void _zfcp_dbf_hba_fsf_unsol(const char *tag, int level, struct zfcp_dbf *dbf, - struct fsf_status_read_buffer *status_buffer) +/** + * zfcp_dbf_hba_fsf_res - trace event for fsf responses + * @tag: tag indicating which kind of unsolicited status has been received + * @req: request for which a response was received + */ +void zfcp_dbf_hba_fsf_res(char *tag, struct zfcp_fsf_req *req) { - struct zfcp_dbf_hba_record *rec = &dbf->hba_buf; + struct zfcp_dbf *dbf = req->adapter->dbf; + struct fsf_qtcb_prefix *q_pref = &req->qtcb->prefix; + struct fsf_qtcb_header *q_head = &req->qtcb->header; + struct zfcp_dbf_hba *rec = &dbf->hba_buf; unsigned long flags; spin_lock_irqsave(&dbf->hba_lock, flags); memset(rec, 0, sizeof(*rec)); - strncpy(rec->tag, "stat", ZFCP_DBF_TAG_SIZE); - strncpy(rec->tag2, tag, ZFCP_DBF_TAG_SIZE); - - rec->u.status.failed = atomic_read(&dbf->adapter->stat_miss); - if (status_buffer != NULL) { - rec->u.status.status_type = status_buffer->status_type; - rec->u.status.status_subtype = status_buffer->status_subtype; - memcpy(&rec->u.status.queue_designator, - &status_buffer->queue_designator, - sizeof(struct fsf_queue_designator)); - - switch (status_buffer->status_type) { - case FSF_STATUS_READ_SENSE_DATA_AVAIL: - rec->u.status.payload_size = - ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL; - break; - case FSF_STATUS_READ_BIT_ERROR_THRESHOLD: - rec->u.status.payload_size = - ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD; - break; - - case FSF_STATUS_READ_LINK_DOWN: - switch (status_buffer->status_subtype) { - case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK: - case FSF_STATUS_READ_SUB_FDISC_FAILED: - rec->u.status.payload_size = - sizeof(struct fsf_link_down_info); - } - break; - - case FSF_STATUS_READ_FEATURE_UPDATE_ALERT: - rec->u.status.payload_size = - ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT; - break; - } - memcpy(&rec->u.status.payload, - &status_buffer->payload, rec->u.status.payload_size); + memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); + rec->id = ZFCP_DBF_HBA_RES; + rec->fsf_req_id = req->req_id; + rec->fsf_req_status = req->status; + rec->fsf_cmd = req->fsf_command; + rec->fsf_seq_no = req->seq_no; + rec->u.res.req_issued = req->issued; + rec->u.res.prot_status = q_pref->prot_status; + rec->u.res.fsf_status = q_head->fsf_status; + + memcpy(rec->u.res.prot_status_qual, &q_pref->prot_status_qual, + FSF_PROT_STATUS_QUAL_SIZE); + memcpy(rec->u.res.fsf_status_qual, &q_head->fsf_status_qual, + FSF_STATUS_QUALIFIER_SIZE); + + if (req->fsf_command != FSF_QTCB_FCP_CMND) { + rec->pl_len = q_head->log_length; + zfcp_dbf_pl_write(dbf, (char *)q_pref + q_head->log_start, + rec->pl_len, "fsf_res", req->req_id); } - debug_event(dbf->hba, level, rec, sizeof(*rec)); + debug_event(dbf->hba, 1, rec, sizeof(*rec)); spin_unlock_irqrestore(&dbf->hba_lock, flags); } /** - * zfcp_dbf_hba_qdio - trace event for QDIO related failure - * @qdio: qdio structure affected by this QDIO related event - * @qdio_error: as passed by qdio module - * @sbal_index: first buffer with error condition, as passed by qdio module - * @sbal_count: number of buffers affected, as passed by qdio module + * zfcp_dbf_hba_fsf_uss - trace event for an unsolicited status buffer + * @tag: tag indicating which kind of unsolicited status has been received + * @req: request providing the unsolicited status */ -void zfcp_dbf_hba_qdio(struct zfcp_dbf *dbf, unsigned int qdio_error, - int sbal_index, int sbal_count) +void zfcp_dbf_hba_fsf_uss(char *tag, struct zfcp_fsf_req *req) { - struct zfcp_dbf_hba_record *r = &dbf->hba_buf; + struct zfcp_dbf *dbf = req->adapter->dbf; + struct fsf_status_read_buffer *srb = req->data; + struct zfcp_dbf_hba *rec = &dbf->hba_buf; unsigned long flags; spin_lock_irqsave(&dbf->hba_lock, flags); - memset(r, 0, sizeof(*r)); - strncpy(r->tag, "qdio", ZFCP_DBF_TAG_SIZE); - r->u.qdio.qdio_error = qdio_error; - r->u.qdio.sbal_index = sbal_index; - r->u.qdio.sbal_count = sbal_count; - debug_event(dbf->hba, 0, r, sizeof(*r)); + memset(rec, 0, sizeof(*rec)); + + memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); + rec->id = ZFCP_DBF_HBA_USS; + rec->fsf_req_id = req->req_id; + rec->fsf_req_status = req->status; + rec->fsf_cmd = req->fsf_command; + + if (!srb) + goto log; + + rec->u.uss.status_type = srb->status_type; + rec->u.uss.status_subtype = srb->status_subtype; + rec->u.uss.d_id = ntoh24(srb->d_id); + rec->u.uss.lun = srb->fcp_lun; + memcpy(&rec->u.uss.queue_designator, &srb->queue_designator, + sizeof(rec->u.uss.queue_designator)); + + /* status read buffer payload length */ + rec->pl_len = (!srb->length) ? 0 : srb->length - + offsetof(struct fsf_status_read_buffer, payload); + + if (rec->pl_len) + zfcp_dbf_pl_write(dbf, srb->payload.data, rec->pl_len, + "fsf_uss", req->req_id); +log: + debug_event(dbf->hba, 2, rec, sizeof(*rec)); spin_unlock_irqrestore(&dbf->hba_lock, flags); } /** - * zfcp_dbf_hba_berr - trace event for bit error threshold - * @dbf: dbf structure affected by this QDIO related event - * @req: fsf request + * zfcp_dbf_hba_bit_err - trace event for bit error conditions + * @tag: tag indicating which kind of unsolicited status has been received + * @req: request which caused the bit_error condition */ -void zfcp_dbf_hba_berr(struct zfcp_dbf *dbf, struct zfcp_fsf_req *req) +void zfcp_dbf_hba_bit_err(char *tag, struct zfcp_fsf_req *req) { - struct zfcp_dbf_hba_record *r = &dbf->hba_buf; + struct zfcp_dbf *dbf = req->adapter->dbf; + struct zfcp_dbf_hba *rec = &dbf->hba_buf; struct fsf_status_read_buffer *sr_buf = req->data; - struct fsf_bit_error_payload *err = &sr_buf->payload.bit_error; unsigned long flags; spin_lock_irqsave(&dbf->hba_lock, flags); - memset(r, 0, sizeof(*r)); - strncpy(r->tag, "berr", ZFCP_DBF_TAG_SIZE); - memcpy(&r->u.berr, err, sizeof(struct fsf_bit_error_payload)); - debug_event(dbf->hba, 0, r, sizeof(*r)); - spin_unlock_irqrestore(&dbf->hba_lock, flags); -} -static void zfcp_dbf_hba_view_response(char **p, - struct zfcp_dbf_hba_record_response *r) -{ - struct timespec t; - - zfcp_dbf_out(p, "fsf_command", "0x%08x", r->fsf_command); - zfcp_dbf_out(p, "fsf_reqid", "0x%0Lx", r->fsf_reqid); - zfcp_dbf_out(p, "fsf_seqno", "0x%08x", r->fsf_seqno); - stck_to_timespec(r->fsf_issued, &t); - zfcp_dbf_out(p, "fsf_issued", "%011lu:%06lu", t.tv_sec, t.tv_nsec); - zfcp_dbf_out(p, "fsf_prot_status", "0x%08x", r->fsf_prot_status); - zfcp_dbf_out(p, "fsf_status", "0x%08x", r->fsf_status); - zfcp_dbf_outd(p, "fsf_prot_status_qual", r->fsf_prot_status_qual, - FSF_PROT_STATUS_QUAL_SIZE, 0, FSF_PROT_STATUS_QUAL_SIZE); - zfcp_dbf_outd(p, "fsf_status_qual", r->fsf_status_qual, - FSF_STATUS_QUALIFIER_SIZE, 0, FSF_STATUS_QUALIFIER_SIZE); - zfcp_dbf_out(p, "fsf_req_status", "0x%08x", r->fsf_req_status); - zfcp_dbf_out(p, "sbal_first", "0x%02x", r->sbal_first); - zfcp_dbf_out(p, "sbal_last", "0x%02x", r->sbal_last); - zfcp_dbf_out(p, "sbal_response", "0x%02x", r->sbal_response); - zfcp_dbf_out(p, "pool", "0x%02x", r->pool); - - switch (r->fsf_command) { - case FSF_QTCB_FCP_CMND: - if (r->fsf_req_status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT) - break; - zfcp_dbf_out(p, "data_direction", "0x%04x", r->u.fcp.data_dir); - zfcp_dbf_out(p, "scsi_cmnd", "0x%0Lx", r->u.fcp.cmnd); - *p += sprintf(*p, "\n"); - break; - - case FSF_QTCB_OPEN_PORT_WITH_DID: - case FSF_QTCB_CLOSE_PORT: - case FSF_QTCB_CLOSE_PHYSICAL_PORT: - zfcp_dbf_out(p, "wwpn", "0x%016Lx", r->u.port.wwpn); - zfcp_dbf_out(p, "d_id", "0x%06x", r->u.port.d_id); - zfcp_dbf_out(p, "port_handle", "0x%08x", r->u.port.port_handle); - break; - - case FSF_QTCB_OPEN_LUN: - case FSF_QTCB_CLOSE_LUN: - zfcp_dbf_out(p, "wwpn", "0x%016Lx", r->u.unit.wwpn); - zfcp_dbf_out(p, "fcp_lun", "0x%016Lx", r->u.unit.fcp_lun); - zfcp_dbf_out(p, "port_handle", "0x%08x", r->u.unit.port_handle); - zfcp_dbf_out(p, "lun_handle", "0x%08x", r->u.unit.lun_handle); - break; - - case FSF_QTCB_SEND_ELS: - zfcp_dbf_out(p, "d_id", "0x%06x", r->u.els.d_id); - break; - - case FSF_QTCB_ABORT_FCP_CMND: - case FSF_QTCB_SEND_GENERIC: - case FSF_QTCB_EXCHANGE_CONFIG_DATA: - case FSF_QTCB_EXCHANGE_PORT_DATA: - case FSF_QTCB_DOWNLOAD_CONTROL_FILE: - case FSF_QTCB_UPLOAD_CONTROL_FILE: - break; - } -} - -static void zfcp_dbf_hba_view_status(char **p, - struct zfcp_dbf_hba_record_status *r) -{ - zfcp_dbf_out(p, "failed", "0x%02x", r->failed); - zfcp_dbf_out(p, "status_type", "0x%08x", r->status_type); - zfcp_dbf_out(p, "status_subtype", "0x%08x", r->status_subtype); - zfcp_dbf_outd(p, "queue_designator", (char *)&r->queue_designator, - sizeof(struct fsf_queue_designator), 0, - sizeof(struct fsf_queue_designator)); - zfcp_dbf_outd(p, "payload", (char *)&r->payload, r->payload_size, 0, - r->payload_size); -} - -static void zfcp_dbf_hba_view_qdio(char **p, struct zfcp_dbf_hba_record_qdio *r) -{ - zfcp_dbf_out(p, "qdio_error", "0x%08x", r->qdio_error); - zfcp_dbf_out(p, "sbal_index", "0x%02x", r->sbal_index); - zfcp_dbf_out(p, "sbal_count", "0x%02x", r->sbal_count); -} - -static void zfcp_dbf_hba_view_berr(char **p, struct fsf_bit_error_payload *r) -{ - zfcp_dbf_out(p, "link_failures", "%d", r->link_failure_error_count); - zfcp_dbf_out(p, "loss_of_sync_err", "%d", r->loss_of_sync_error_count); - zfcp_dbf_out(p, "loss_of_sig_err", "%d", r->loss_of_signal_error_count); - zfcp_dbf_out(p, "prim_seq_err", "%d", - r->primitive_sequence_error_count); - zfcp_dbf_out(p, "inval_trans_word_err", "%d", - r->invalid_transmission_word_error_count); - zfcp_dbf_out(p, "CRC_errors", "%d", r->crc_error_count); - zfcp_dbf_out(p, "prim_seq_event_to", "%d", - r->primitive_sequence_event_timeout_count); - zfcp_dbf_out(p, "elast_buf_overrun_err", "%d", - r->elastic_buffer_overrun_error_count); - zfcp_dbf_out(p, "adv_rec_buf2buf_cred", "%d", - r->advertised_receive_b2b_credit); - zfcp_dbf_out(p, "curr_rec_buf2buf_cred", "%d", - r->current_receive_b2b_credit); - zfcp_dbf_out(p, "adv_trans_buf2buf_cred", "%d", - r->advertised_transmit_b2b_credit); - zfcp_dbf_out(p, "curr_trans_buf2buf_cred", "%d", - r->current_transmit_b2b_credit); -} - -static int zfcp_dbf_hba_view_format(debug_info_t *id, struct debug_view *view, - char *out_buf, const char *in_buf) -{ - struct zfcp_dbf_hba_record *r = (struct zfcp_dbf_hba_record *)in_buf; - char *p = out_buf; - - if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0) - return 0; + memset(rec, 0, sizeof(*rec)); - zfcp_dbf_tag(&p, "tag", r->tag); - if (isalpha(r->tag2[0])) - zfcp_dbf_tag(&p, "tag2", r->tag2); - - if (strncmp(r->tag, "resp", ZFCP_DBF_TAG_SIZE) == 0) - zfcp_dbf_hba_view_response(&p, &r->u.response); - else if (strncmp(r->tag, "stat", ZFCP_DBF_TAG_SIZE) == 0) - zfcp_dbf_hba_view_status(&p, &r->u.status); - else if (strncmp(r->tag, "qdio", ZFCP_DBF_TAG_SIZE) == 0) - zfcp_dbf_hba_view_qdio(&p, &r->u.qdio); - else if (strncmp(r->tag, "berr", ZFCP_DBF_TAG_SIZE) == 0) - zfcp_dbf_hba_view_berr(&p, &r->u.berr); - - if (strncmp(r->tag, "resp", ZFCP_DBF_TAG_SIZE) != 0) - p += sprintf(p, "\n"); - return p - out_buf; + memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); + rec->id = ZFCP_DBF_HBA_BIT; + rec->fsf_req_id = req->req_id; + rec->fsf_req_status = req->status; + rec->fsf_cmd = req->fsf_command; + memcpy(&rec->u.be, &sr_buf->payload.bit_error, + sizeof(struct fsf_bit_error_payload)); + + debug_event(dbf->hba, 1, rec, sizeof(*rec)); + spin_unlock_irqrestore(&dbf->hba_lock, flags); } -static struct debug_view zfcp_dbf_hba_view = { - .name = "structured", - .header_proc = zfcp_dbf_view_header, - .format_proc = zfcp_dbf_hba_view_format, -}; - static void zfcp_dbf_set_common(struct zfcp_dbf_rec *rec, struct zfcp_adapter *adapter, struct zfcp_port *port, @@ -758,6 +551,7 @@ int zfcp_dbf_adapter_register(struct zfcp_adapter *adapter) dbf->adapter = adapter; + spin_lock_init(&dbf->pay_lock); spin_lock_init(&dbf->hba_lock); spin_lock_init(&dbf->san_lock); spin_lock_init(&dbf->scsi_lock); @@ -771,11 +565,17 @@ int zfcp_dbf_adapter_register(struct zfcp_adapter *adapter) /* debug feature area which records HBA (FSF and QDIO) conditions */ sprintf(dbf_name, "zfcp_%s_hba", dev_name(&adapter->ccw_device->dev)); - dbf->hba = zfcp_dbf_reg(dbf_name, 3, &zfcp_dbf_hba_view, - sizeof(struct zfcp_dbf_hba_record)); + dbf->hba = zfcp_dbf_reg(dbf_name, 3, NULL, sizeof(struct zfcp_dbf_hba)); if (!dbf->hba) goto err_out; + /* debug feature area which records payload info */ + sprintf(dbf_name, "zfcp_%s_pay", dev_name(&adapter->ccw_device->dev)); + dbf->pay = zfcp_dbf_reg(dbf_name, 3, NULL, + sizeof(struct zfcp_dbf_pay)); + if (!dbf->pay) + goto err_out; + /* debug feature area which records SAN command failures and recovery */ sprintf(dbf_name, "zfcp_%s_san", dev_name(&adapter->ccw_device->dev)); dbf->san = zfcp_dbf_reg(dbf_name, 3, NULL, sizeof(struct zfcp_dbf_san)); @@ -808,6 +608,7 @@ void zfcp_dbf_adapter_unregister(struct zfcp_dbf *dbf) debug_unregister(dbf->scsi); debug_unregister(dbf->san); debug_unregister(dbf->hba); + debug_unregister(dbf->pay); debug_unregister(dbf->rec); dbf->adapter->dbf = NULL; kfree(dbf); diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h index a3af6bd3d5aa..5dc0b414cf28 100644 --- a/drivers/s390/scsi/zfcp_dbf.h +++ b/drivers/s390/scsi/zfcp_dbf.h @@ -1,22 +1,8 @@ /* - * This file is part of the zfcp device driver for - * FCP adapters for IBM System z9 and zSeries. + * zfcp device driver + * debug feature declarations * - * Copyright IBM Corp. 2008, 2009 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Copyright IBM Corp. 2008, 2010 */ #ifndef ZFCP_DBF_H @@ -136,73 +122,90 @@ struct zfcp_dbf_san { char payload[ZFCP_DBF_SAN_MAX_PAYLOAD]; } __packed; -struct zfcp_dbf_hba_record_response { - u32 fsf_command; - u64 fsf_reqid; - u32 fsf_seqno; - u64 fsf_issued; - u32 fsf_prot_status; +/** + * struct zfcp_dbf_hba_res - trace record for hba responses + * @req_issued: timestamp when request was issued + * @prot_status: protocol status + * @prot_status_qual: protocol status qualifier + * @fsf_status: fsf status + * @fsf_status_qual: fsf status qualifier + */ +struct zfcp_dbf_hba_res { + u64 req_issued; + u32 prot_status; + u8 prot_status_qual[FSF_PROT_STATUS_QUAL_SIZE]; u32 fsf_status; - u8 fsf_prot_status_qual[FSF_PROT_STATUS_QUAL_SIZE]; - u8 fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE]; - u32 fsf_req_status; - u8 sbal_first; - u8 sbal_last; - u8 sbal_response; - u8 pool; - u64 erp_action; - union { - struct { - u64 cmnd; - u32 data_dir; - } fcp; - struct { - u64 wwpn; - u32 d_id; - u32 port_handle; - } port; - struct { - u64 wwpn; - u64 fcp_lun; - u32 port_handle; - u32 lun_handle; - } unit; - struct { - u32 d_id; - } els; - } u; -} __attribute__ ((packed)); + u8 fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE]; +} __packed; -struct zfcp_dbf_hba_record_status { - u8 failed; +/** + * struct zfcp_dbf_hba_uss - trace record for unsolicited status + * @status_type: type of unsolicited status + * @status_subtype: subtype of unsolicited status + * @d_id: destination ID + * @lun: logical unit number + * @queue_designator: queue designator + */ +struct zfcp_dbf_hba_uss { u32 status_type; u32 status_subtype; - struct fsf_queue_designator - queue_designator; - u32 payload_size; -#define ZFCP_DBF_UNSOL_PAYLOAD 80 -#define ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL 32 -#define ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD 56 -#define ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT 2 * sizeof(u32) - u8 payload[ZFCP_DBF_UNSOL_PAYLOAD]; -} __attribute__ ((packed)); + u32 d_id; + u64 lun; + u64 queue_designator; +} __packed; -struct zfcp_dbf_hba_record_qdio { - u32 qdio_error; - u8 sbal_index; - u8 sbal_count; -} __attribute__ ((packed)); +/** + * enum zfcp_dbf_hba_id - HBA trace record identifier + * @ZFCP_DBF_HBA_RES: response trace record + * @ZFCP_DBF_HBA_USS: unsolicited status trace record + * @ZFCP_DBF_HBA_BIT: bit error trace record + */ +enum zfcp_dbf_hba_id { + ZFCP_DBF_HBA_RES = 1, + ZFCP_DBF_HBA_USS = 2, + ZFCP_DBF_HBA_BIT = 3, +}; -struct zfcp_dbf_hba_record { - u8 tag[ZFCP_DBF_TAG_SIZE]; - u8 tag2[ZFCP_DBF_TAG_SIZE]; +/** + * struct zfcp_dbf_hba - common trace record for HBA records + * @id: unique number of recovery record type + * @tag: identifier string specifying the location of initiation + * @fsf_req_id: request id for fsf requests + * @fsf_req_status: status of fsf request + * @fsf_cmd: fsf command + * @fsf_seq_no: fsf sequence number + * @pl_len: length of payload stored as zfcp_dbf_pay + * @u: record type specific data + */ +struct zfcp_dbf_hba { + u8 id; + char tag[ZFCP_DBF_TAG_LEN]; + u64 fsf_req_id; + u32 fsf_req_status; + u32 fsf_cmd; + u32 fsf_seq_no; + u16 pl_len; union { - struct zfcp_dbf_hba_record_response response; - struct zfcp_dbf_hba_record_status status; - struct zfcp_dbf_hba_record_qdio qdio; - struct fsf_bit_error_payload berr; + struct zfcp_dbf_hba_res res; + struct zfcp_dbf_hba_uss uss; + struct fsf_bit_error_payload be; } u; -} __attribute__ ((packed)); +} __packed; + +/** + * struct zfcp_dbf_pay - trace record for unformatted payload information + * @area: area this record is originated from + * @counter: ascending record number + * @fsf_req_id: request id of fsf request + * @data: unformatted data + */ +struct zfcp_dbf_pay { + char area[ZFCP_DBF_TAG_LEN]; + char counter; + u64 fsf_req_id; +#define ZFCP_DBF_PAY_MAX_REC 0x100 + char data[ZFCP_DBF_PAY_MAX_REC]; +} __packed; struct zfcp_dbf_scsi_record { u8 tag[ZFCP_DBF_TAG_SIZE]; @@ -230,71 +233,57 @@ struct zfcp_dbf_scsi_record { } __attribute__ ((packed)); struct zfcp_dbf { + debug_info_t *pay; debug_info_t *rec; debug_info_t *hba; debug_info_t *san; debug_info_t *scsi; + spinlock_t pay_lock; spinlock_t rec_lock; spinlock_t hba_lock; spinlock_t san_lock; spinlock_t scsi_lock; struct zfcp_dbf_rec rec_buf; - struct zfcp_dbf_hba_record hba_buf; + struct zfcp_dbf_hba hba_buf; struct zfcp_dbf_san san_buf; struct zfcp_dbf_scsi_record scsi_buf; + struct zfcp_dbf_pay pay_buf; struct zfcp_adapter *adapter; }; static inline -void zfcp_dbf_hba_fsf_resp(const char *tag2, int level, - struct zfcp_fsf_req *req, struct zfcp_dbf *dbf) +void zfcp_dbf_hba_fsf_resp(char *tag, int level, struct zfcp_fsf_req *req) { - if (level <= dbf->hba->level) - _zfcp_dbf_hba_fsf_response(tag2, level, req, dbf); + if (level <= req->adapter->dbf->hba->level) + zfcp_dbf_hba_fsf_res(tag, req); } /** * zfcp_dbf_hba_fsf_response - trace event for request completion * @fsf_req: request that has been completed */ -static inline void zfcp_dbf_hba_fsf_response(struct zfcp_fsf_req *req) +static inline +void zfcp_dbf_hba_fsf_response(struct zfcp_fsf_req *req) { - struct zfcp_dbf *dbf = req->adapter->dbf; struct fsf_qtcb *qtcb = req->qtcb; if ((qtcb->prefix.prot_status != FSF_PROT_GOOD) && (qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) { - zfcp_dbf_hba_fsf_resp("perr", 1, req, dbf); + zfcp_dbf_hba_fsf_resp("fs_perr", 1, req); } else if (qtcb->header.fsf_status != FSF_GOOD) { - zfcp_dbf_hba_fsf_resp("ferr", 1, req, dbf); + zfcp_dbf_hba_fsf_resp("fs_ferr", 1, req); } else if ((req->fsf_command == FSF_QTCB_OPEN_PORT_WITH_DID) || (req->fsf_command == FSF_QTCB_OPEN_LUN)) { - zfcp_dbf_hba_fsf_resp("open", 4, req, dbf); + zfcp_dbf_hba_fsf_resp("fs_open", 4, req); } else if (qtcb->header.log_length) { - zfcp_dbf_hba_fsf_resp("qtcb", 5, req, dbf); + zfcp_dbf_hba_fsf_resp("fs_qtcb", 5, req); } else { - zfcp_dbf_hba_fsf_resp("norm", 6, req, dbf); + zfcp_dbf_hba_fsf_resp("fs_norm", 6, req); } - } - -/** - * zfcp_dbf_hba_fsf_unsol - trace event for an unsolicited status buffer - * @tag: tag indicating which kind of unsolicited status has been received - * @dbf: reference to dbf structure - * @status_buffer: buffer containing payload of unsolicited status - */ -static inline -void zfcp_dbf_hba_fsf_unsol(const char *tag, struct zfcp_dbf *dbf, - struct fsf_status_read_buffer *buf) -{ - int level = 2; - - if (level <= dbf->hba->level) - _zfcp_dbf_hba_fsf_unsol(tag, level, dbf, buf); } static inline diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index ff7effe55379..00875de2cb99 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -49,11 +49,9 @@ extern void zfcp_dbf_adapter_unregister(struct zfcp_dbf *); extern void zfcp_dbf_rec_trig(char *, struct zfcp_adapter *, struct zfcp_port *, struct scsi_device *, u8, u8); extern void zfcp_dbf_rec_run(char *, struct zfcp_erp_action *); -extern void _zfcp_dbf_hba_fsf_response(const char *, int, struct zfcp_fsf_req *, - struct zfcp_dbf *); -extern void _zfcp_dbf_hba_fsf_unsol(const char *, int level, struct zfcp_dbf *, - struct fsf_status_read_buffer *); -extern void zfcp_dbf_hba_qdio(struct zfcp_dbf *, unsigned int, int, int); +extern void zfcp_dbf_hba_fsf_uss(char *, struct zfcp_fsf_req *); +extern void zfcp_dbf_hba_fsf_res(char *, struct zfcp_fsf_req *); +extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *); extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32); extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *); @@ -141,6 +139,8 @@ extern int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *, struct zfcp_qdio_req *, extern int zfcp_qdio_open(struct zfcp_qdio *); extern void zfcp_qdio_close(struct zfcp_qdio *); extern void zfcp_qdio_siosl(struct zfcp_adapter *); +extern struct zfcp_fsf_req *zfcp_fsf_get_req(struct zfcp_qdio *, + struct qdio_buffer *); /* zfcp_scsi.c */ extern struct zfcp_data zfcp_data; diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 6d805c50627f..9881ba947f11 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -211,13 +211,13 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req) struct fsf_status_read_buffer *sr_buf = req->data; if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { - zfcp_dbf_hba_fsf_unsol("dism", adapter->dbf, sr_buf); + zfcp_dbf_hba_fsf_uss("fssrh_1", req); mempool_free(sr_buf, adapter->pool.status_read_data); zfcp_fsf_req_free(req); return; } - zfcp_dbf_hba_fsf_unsol("read", adapter->dbf, sr_buf); + zfcp_dbf_hba_fsf_uss("fssrh_2", req); switch (sr_buf->status_type) { case FSF_STATUS_READ_PORT_CLOSED: @@ -232,7 +232,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req) dev_warn(&adapter->ccw_device->dev, "The error threshold for checksum statistics " "has been exceeded\n"); - zfcp_dbf_hba_berr(adapter->dbf, req); + zfcp_dbf_hba_bit_err("fssrh_3", req); break; case FSF_STATUS_READ_LINK_DOWN: zfcp_fsf_status_read_link_down(req); @@ -754,10 +754,11 @@ int zfcp_fsf_status_read(struct zfcp_qdio *qdio) goto out; failed_req_send: + req->data = NULL; mempool_free(sr_buf, adapter->pool.status_read_data); failed_buf: + zfcp_dbf_hba_fsf_uss("fssr__1", req); zfcp_fsf_req_free(req); - zfcp_dbf_hba_fsf_unsol("fail", adapter->dbf, NULL); out: spin_unlock_irq(&qdio->req_q_lock); return retval; @@ -2420,3 +2421,12 @@ void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx) break; } } + +struct zfcp_fsf_req *zfcp_fsf_get_req(struct zfcp_qdio *qdio, + struct qdio_buffer *sbal) +{ + struct qdio_buffer_element *sbale = &sbal->element[0]; + u64 req_id = (unsigned long) sbale->addr; + + return zfcp_reqlist_find(qdio->adapter->req_list, req_id); +} diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index a0554beb4179..434a33ba0509 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -74,7 +74,6 @@ static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err, struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm; if (unlikely(qdio_err)) { - zfcp_dbf_hba_qdio(qdio->adapter->dbf, qdio_err, idx, count); zfcp_qdio_handler_error(qdio, "qdireq1", qdio_err); return; } @@ -97,7 +96,6 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err, int sbal_idx, sbal_no; if (unlikely(qdio_err)) { - zfcp_dbf_hba_qdio(qdio->adapter->dbf, qdio_err, idx, count); zfcp_qdio_handler_error(qdio, "qdires1", qdio_err); return; } -- cgit v1.2.3-59-g8ed1b From 250a1352b95e1db3216e5c5d4f4365bea5122f4a Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Thu, 2 Dec 2010 15:16:15 +0100 Subject: [SCSI] zfcp: Redesign of the debug tracing for SCSI records. This patch is the continuation to redesign the zfcp tracing to a more straight-forward and easy to extend scheme. This patch deals with all trace records of the zfcp SCSI area. Signed-off-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_dbf.c | 232 +++++++++--------------------------------- drivers/s390/scsi/zfcp_dbf.h | 129 ++++++++++++----------- drivers/s390/scsi/zfcp_ext.h | 4 +- drivers/s390/scsi/zfcp_fsf.c | 2 +- drivers/s390/scsi/zfcp_scsi.c | 30 +++--- 5 files changed, 132 insertions(+), 265 deletions(-) diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index b57a47b64b80..f9bd094c6e63 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -3,7 +3,7 @@ * * Debug traces for zfcp. * - * Copyright IBM Corporation 2002, 2009 + * Copyright IBM Corporation 2002, 2010 */ #define KMSG_COMPONENT "zfcp" @@ -52,70 +52,6 @@ void zfcp_dbf_pl_write(struct zfcp_dbf *dbf, void *data, u16 length, char *area, spin_unlock(&dbf->pay_lock); } -static void zfcp_dbf_tag(char **p, const char *label, const char *tag) -{ - int i; - - *p += sprintf(*p, "%-24s", label); - for (i = 0; i < ZFCP_DBF_TAG_SIZE; i++) - *p += sprintf(*p, "%c", tag[i]); - *p += sprintf(*p, "\n"); -} - -static void zfcp_dbf_out(char **buf, const char *s, const char *format, ...) -{ - va_list arg; - - *buf += sprintf(*buf, "%-24s", s); - va_start(arg, format); - *buf += vsprintf(*buf, format, arg); - va_end(arg); - *buf += sprintf(*buf, "\n"); -} - -static void zfcp_dbf_outd(char **p, const char *label, char *buffer, - int buflen, int offset, int total_size) -{ - if (!offset) - *p += sprintf(*p, "%-24s ", label); - while (buflen--) { - if (offset > 0) { - if ((offset % 32) == 0) - *p += sprintf(*p, "\n%-24c ", ' '); - else if ((offset % 4) == 0) - *p += sprintf(*p, " "); - } - *p += sprintf(*p, "%02x", *buffer++); - if (++offset == total_size) { - *p += sprintf(*p, "\n"); - break; - } - } - if (!total_size) - *p += sprintf(*p, "\n"); -} - -static int zfcp_dbf_view_header(debug_info_t *id, struct debug_view *view, - int area, debug_entry_t *entry, char *out_buf) -{ - struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)DEBUG_DATA(entry); - struct timespec t; - char *p = out_buf; - - if (strncmp(dump->tag, "dump", ZFCP_DBF_TAG_SIZE) != 0) { - stck_to_timespec(entry->id.stck, &t); - zfcp_dbf_out(&p, "timestamp", "%011lu:%06lu", - t.tv_sec, t.tv_nsec); - zfcp_dbf_out(&p, "cpu", "%02i", entry->id.fields.cpuid); - } else { - zfcp_dbf_outd(&p, "", dump->data, dump->size, dump->offset, - dump->total_size); - if ((dump->offset + dump->size) == dump->total_size) - p += sprintf(p, "\n"); - } - return p - out_buf; -} - /** * zfcp_dbf_hba_fsf_res - trace event for fsf responses * @tag: tag indicating which kind of unsolicited status has been received @@ -393,131 +329,57 @@ void zfcp_dbf_san_in_els(char *tag, struct zfcp_fsf_req *fsf) fsf->req_id, ntoh24(srb->d_id)); } -void _zfcp_dbf_scsi(const char *tag, const char *tag2, int level, - struct zfcp_dbf *dbf, struct scsi_cmnd *scsi_cmnd, - struct zfcp_fsf_req *fsf_req, unsigned long old_req_id) +/** + * zfcp_dbf_scsi - trace event for scsi commands + * @tag: identifier for event + * @sc: pointer to struct scsi_cmnd + * @fsf: pointer to struct zfcp_fsf_req + */ +void zfcp_dbf_scsi(char *tag, struct scsi_cmnd *sc, struct zfcp_fsf_req *fsf) { - struct zfcp_dbf_scsi_record *rec = &dbf->scsi_buf; - struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec; - unsigned long flags; + struct zfcp_adapter *adapter = + (struct zfcp_adapter *) sc->device->host->hostdata[0]; + struct zfcp_dbf *dbf = adapter->dbf; + struct zfcp_dbf_scsi *rec = &dbf->scsi_buf; struct fcp_resp_with_ext *fcp_rsp; - struct fcp_resp_rsp_info *fcp_rsp_info = NULL; - char *fcp_sns_info = NULL; - int offset = 0, buflen = 0; + struct fcp_resp_rsp_info *fcp_rsp_info; + unsigned long flags; spin_lock_irqsave(&dbf->scsi_lock, flags); - do { - memset(rec, 0, sizeof(*rec)); - if (offset == 0) { - strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE); - strncpy(rec->tag2, tag2, ZFCP_DBF_TAG_SIZE); - if (scsi_cmnd != NULL) { - if (scsi_cmnd->device) { - rec->scsi_id = scsi_cmnd->device->id; - rec->scsi_lun = scsi_cmnd->device->lun; - } - rec->scsi_result = scsi_cmnd->result; - rec->scsi_cmnd = (unsigned long)scsi_cmnd; - memcpy(rec->scsi_opcode, scsi_cmnd->cmnd, - min((int)scsi_cmnd->cmd_len, - ZFCP_DBF_SCSI_OPCODE)); - rec->scsi_retries = scsi_cmnd->retries; - rec->scsi_allowed = scsi_cmnd->allowed; - } - if (fsf_req != NULL) { - fcp_rsp = (struct fcp_resp_with_ext *) - &(fsf_req->qtcb->bottom.io.fcp_rsp); - fcp_rsp_info = (struct fcp_resp_rsp_info *) - &fcp_rsp[1]; - fcp_sns_info = (char *) &fcp_rsp[1]; - if (fcp_rsp->resp.fr_flags & FCP_RSP_LEN_VAL) - fcp_sns_info += fcp_rsp->ext.fr_sns_len; - - rec->rsp_validity = fcp_rsp->resp.fr_flags; - rec->rsp_scsi_status = fcp_rsp->resp.fr_status; - rec->rsp_resid = fcp_rsp->ext.fr_resid; - if (fcp_rsp->resp.fr_flags & FCP_RSP_LEN_VAL) - rec->rsp_code = fcp_rsp_info->rsp_code; - if (fcp_rsp->resp.fr_flags & FCP_SNS_LEN_VAL) { - buflen = min(fcp_rsp->ext.fr_sns_len, - (u32)ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO); - rec->sns_info_len = buflen; - memcpy(rec->sns_info, fcp_sns_info, - min(buflen, - ZFCP_DBF_SCSI_FCP_SNS_INFO)); - offset += min(buflen, - ZFCP_DBF_SCSI_FCP_SNS_INFO); - } - - rec->fsf_reqid = fsf_req->req_id; - rec->fsf_seqno = fsf_req->seq_no; - rec->fsf_issued = fsf_req->issued; - } - rec->old_fsf_reqid = old_req_id; - } else { - strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE); - dump->total_size = buflen; - dump->offset = offset; - dump->size = min(buflen - offset, - (int)sizeof(struct - zfcp_dbf_scsi_record) - - (int)sizeof(struct zfcp_dbf_dump)); - memcpy(dump->data, fcp_sns_info + offset, dump->size); - offset += dump->size; - } - debug_event(dbf->scsi, level, rec, sizeof(*rec)); - } while (offset < buflen); - spin_unlock_irqrestore(&dbf->scsi_lock, flags); -} + memset(rec, 0, sizeof(*rec)); -static int zfcp_dbf_scsi_view_format(debug_info_t *id, struct debug_view *view, - char *out_buf, const char *in_buf) -{ - struct zfcp_dbf_scsi_record *r = (struct zfcp_dbf_scsi_record *)in_buf; - struct timespec t; - char *p = out_buf; - - if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0) - return 0; - - zfcp_dbf_tag(&p, "tag", r->tag); - zfcp_dbf_tag(&p, "tag2", r->tag2); - zfcp_dbf_out(&p, "scsi_id", "0x%08x", r->scsi_id); - zfcp_dbf_out(&p, "scsi_lun", "0x%08x", r->scsi_lun); - zfcp_dbf_out(&p, "scsi_result", "0x%08x", r->scsi_result); - zfcp_dbf_out(&p, "scsi_cmnd", "0x%0Lx", r->scsi_cmnd); - zfcp_dbf_outd(&p, "scsi_opcode", r->scsi_opcode, ZFCP_DBF_SCSI_OPCODE, - 0, ZFCP_DBF_SCSI_OPCODE); - zfcp_dbf_out(&p, "scsi_retries", "0x%02x", r->scsi_retries); - zfcp_dbf_out(&p, "scsi_allowed", "0x%02x", r->scsi_allowed); - if (strncmp(r->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) - zfcp_dbf_out(&p, "old_fsf_reqid", "0x%0Lx", r->old_fsf_reqid); - zfcp_dbf_out(&p, "fsf_reqid", "0x%0Lx", r->fsf_reqid); - zfcp_dbf_out(&p, "fsf_seqno", "0x%08x", r->fsf_seqno); - stck_to_timespec(r->fsf_issued, &t); - zfcp_dbf_out(&p, "fsf_issued", "%011lu:%06lu", t.tv_sec, t.tv_nsec); - - if (strncmp(r->tag, "rslt", ZFCP_DBF_TAG_SIZE) == 0) { - zfcp_dbf_out(&p, "fcp_rsp_validity", "0x%02x", r->rsp_validity); - zfcp_dbf_out(&p, "fcp_rsp_scsi_status", "0x%02x", - r->rsp_scsi_status); - zfcp_dbf_out(&p, "fcp_rsp_resid", "0x%08x", r->rsp_resid); - zfcp_dbf_out(&p, "fcp_rsp_code", "0x%08x", r->rsp_code); - zfcp_dbf_out(&p, "fcp_sns_info_len", "0x%08x", r->sns_info_len); - zfcp_dbf_outd(&p, "fcp_sns_info", r->sns_info, - min((int)r->sns_info_len, - ZFCP_DBF_SCSI_FCP_SNS_INFO), 0, - r->sns_info_len); + memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); + rec->id = ZFCP_DBF_SCSI_CMND; + rec->scsi_result = sc->result; + rec->scsi_retries = sc->retries; + rec->scsi_allowed = sc->allowed; + rec->scsi_id = sc->device->id; + rec->scsi_lun = sc->device->lun; + rec->host_scribble = (unsigned long)sc->host_scribble; + + memcpy(rec->scsi_opcode, sc->cmnd, + min((int)sc->cmd_len, ZFCP_DBF_SCSI_OPCODE)); + + if (fsf) { + rec->fsf_req_id = fsf->req_id; + fcp_rsp = (struct fcp_resp_with_ext *) + &(fsf->qtcb->bottom.io.fcp_rsp); + memcpy(&rec->fcp_rsp, fcp_rsp, FCP_RESP_WITH_EXT); + if (fcp_rsp->resp.fr_flags & FCP_RSP_LEN_VAL) { + fcp_rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1]; + rec->fcp_rsp_info = fcp_rsp_info->rsp_code; + } + if (fcp_rsp->resp.fr_flags & FCP_SNS_LEN_VAL) { + rec->pl_len = min((u16)SCSI_SENSE_BUFFERSIZE, + (u16)ZFCP_DBF_PAY_MAX_REC); + zfcp_dbf_pl_write(dbf, sc->sense_buffer, rec->pl_len, + "fcp_sns", fsf->req_id); + } } - p += sprintf(p, "\n"); - return p - out_buf; -} -static struct debug_view zfcp_dbf_scsi_view = { - .name = "structured", - .header_proc = zfcp_dbf_view_header, - .format_proc = zfcp_dbf_scsi_view_format, -}; + debug_event(adapter->dbf->scsi, 1, rec, sizeof(*rec)); + spin_unlock_irqrestore(&dbf->scsi_lock, flags); +} static debug_info_t *zfcp_dbf_reg(const char *name, int level, struct debug_view *view, int size) @@ -584,8 +446,8 @@ int zfcp_dbf_adapter_register(struct zfcp_adapter *adapter) /* debug feature area which records SCSI command failures and recovery */ sprintf(dbf_name, "zfcp_%s_scsi", dev_name(&adapter->ccw_device->dev)); - dbf->scsi = zfcp_dbf_reg(dbf_name, 3, &zfcp_dbf_scsi_view, - sizeof(struct zfcp_dbf_scsi_record)); + dbf->scsi = zfcp_dbf_reg(dbf_name, 3, NULL, + sizeof(struct zfcp_dbf_scsi)); if (!dbf->scsi) goto err_out; diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h index 5dc0b414cf28..2cee8197dd02 100644 --- a/drivers/s390/scsi/zfcp_dbf.h +++ b/drivers/s390/scsi/zfcp_dbf.h @@ -19,14 +19,6 @@ #define ZFCP_DBF_INVALID_LUN 0xFFFFFFFFFFFFFFFFull -struct zfcp_dbf_dump { - u8 tag[ZFCP_DBF_TAG_SIZE]; - u32 total_size; /* size of total dump data */ - u32 offset; /* how much data has being already dumped */ - u32 size; /* how much data comes with this record */ - u8 data[]; /* dump data */ -} __attribute__ ((packed)); - /** * struct zfcp_dbf_rec_trigger - trace record for triggered recovery action * @ready: number of ready recovery actions @@ -192,6 +184,47 @@ struct zfcp_dbf_hba { } u; } __packed; +/** + * enum zfcp_dbf_scsi_id - scsi trace record identifier + * @ZFCP_DBF_SCSI_CMND: scsi command trace record + */ +enum zfcp_dbf_scsi_id { + ZFCP_DBF_SCSI_CMND = 1, +}; + +/** + * struct zfcp_dbf_scsi - common trace record for SCSI records + * @id: unique number of recovery record type + * @tag: identifier string specifying the location of initiation + * @scsi_id: scsi device id + * @scsi_lun: scsi device logical unit number + * @scsi_result: scsi result + * @scsi_retries: current retry number of scsi request + * @scsi_allowed: allowed retries + * @fcp_rsp_info: FCP response info + * @scsi_opcode: scsi opcode + * @fsf_req_id: request id of fsf request + * @host_scribble: LLD specific data attached to SCSI request + * @pl_len: length of paload stored as zfcp_dbf_pay + * @fsf_rsp: response for fsf request + */ +struct zfcp_dbf_scsi { + u8 id; + char tag[ZFCP_DBF_TAG_LEN]; + u32 scsi_id; + u32 scsi_lun; + u32 scsi_result; + u8 scsi_retries; + u8 scsi_allowed; + u8 fcp_rsp_info; +#define ZFCP_DBF_SCSI_OPCODE 16 + u8 scsi_opcode[ZFCP_DBF_SCSI_OPCODE]; + u64 fsf_req_id; + u64 host_scribble; + u16 pl_len; + struct fcp_resp_with_ext fcp_rsp; +} __packed; + /** * struct zfcp_dbf_pay - trace record for unformatted payload information * @area: area this record is originated from @@ -207,31 +240,6 @@ struct zfcp_dbf_pay { char data[ZFCP_DBF_PAY_MAX_REC]; } __packed; -struct zfcp_dbf_scsi_record { - u8 tag[ZFCP_DBF_TAG_SIZE]; - u8 tag2[ZFCP_DBF_TAG_SIZE]; - u32 scsi_id; - u32 scsi_lun; - u32 scsi_result; - u64 scsi_cmnd; -#define ZFCP_DBF_SCSI_OPCODE 16 - u8 scsi_opcode[ZFCP_DBF_SCSI_OPCODE]; - u8 scsi_retries; - u8 scsi_allowed; - u64 fsf_reqid; - u32 fsf_seqno; - u64 fsf_issued; - u64 old_fsf_reqid; - u8 rsp_validity; - u8 rsp_scsi_status; - u32 rsp_resid; - u8 rsp_code; -#define ZFCP_DBF_SCSI_FCP_SNS_INFO 16 -#define ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO 256 - u32 sns_info_len; - u8 sns_info[ZFCP_DBF_SCSI_FCP_SNS_INFO]; -} __attribute__ ((packed)); - struct zfcp_dbf { debug_info_t *pay; debug_info_t *rec; @@ -246,7 +254,7 @@ struct zfcp_dbf { struct zfcp_dbf_rec rec_buf; struct zfcp_dbf_hba hba_buf; struct zfcp_dbf_san san_buf; - struct zfcp_dbf_scsi_record scsi_buf; + struct zfcp_dbf_scsi scsi_buf; struct zfcp_dbf_pay pay_buf; struct zfcp_adapter *adapter; }; @@ -260,7 +268,7 @@ void zfcp_dbf_hba_fsf_resp(char *tag, int level, struct zfcp_fsf_req *req) /** * zfcp_dbf_hba_fsf_response - trace event for request completion - * @fsf_req: request that has been completed + * @req: request that has been completed */ static inline void zfcp_dbf_hba_fsf_response(struct zfcp_fsf_req *req) @@ -287,57 +295,53 @@ void zfcp_dbf_hba_fsf_response(struct zfcp_fsf_req *req) } static inline -void zfcp_dbf_scsi(const char *tag, const char *tag2, int level, - struct zfcp_dbf *dbf, struct scsi_cmnd *scmd, - struct zfcp_fsf_req *req, unsigned long old_id) +void _zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *scmd, + struct zfcp_fsf_req *req) { - if (level <= dbf->scsi->level) - _zfcp_dbf_scsi(tag, tag2, level, dbf, scmd, req, old_id); + struct zfcp_adapter *adapter = (struct zfcp_adapter *) + scmd->device->host->hostdata[0]; + + if (level <= adapter->dbf->scsi->level) + zfcp_dbf_scsi(tag, scmd, req); } /** * zfcp_dbf_scsi_result - trace event for SCSI command completion - * @dbf: adapter dbf trace * @scmd: SCSI command pointer * @req: FSF request used to issue SCSI command */ static inline -void zfcp_dbf_scsi_result(struct zfcp_dbf *dbf, struct scsi_cmnd *scmd, - struct zfcp_fsf_req *req) +void zfcp_dbf_scsi_result(struct scsi_cmnd *scmd, struct zfcp_fsf_req *req) { if (scmd->result != 0) - zfcp_dbf_scsi("rslt", "erro", 3, dbf, scmd, req, 0); + _zfcp_dbf_scsi("rsl_err", 3, scmd, req); else if (scmd->retries > 0) - zfcp_dbf_scsi("rslt", "retr", 4, dbf, scmd, req, 0); + _zfcp_dbf_scsi("rsl_ret", 4, scmd, req); else - zfcp_dbf_scsi("rslt", "norm", 6, dbf, scmd, req, 0); + _zfcp_dbf_scsi("rsl_nor", 6, scmd, req); } /** * zfcp_dbf_scsi_fail_send - trace event for failure to send SCSI command - * @dbf: adapter dbf trace * @scmd: SCSI command pointer */ static inline -void zfcp_dbf_scsi_fail_send(struct zfcp_dbf *dbf, struct scsi_cmnd *scmd) +void zfcp_dbf_scsi_fail_send(struct scsi_cmnd *scmd) { - zfcp_dbf_scsi("rslt", "fail", 4, dbf, scmd, NULL, 0); + _zfcp_dbf_scsi("rsl_fai", 4, scmd, NULL); } /** * zfcp_dbf_scsi_abort - trace event for SCSI command abort * @tag: tag indicating success or failure of abort operation - * @adapter: adapter thas has been used to issue SCSI command to be aborted * @scmd: SCSI command to be aborted - * @new_req: request containing abort (might be NULL) - * @old_id: identifier of request containg SCSI command to be aborted + * @fsf_req: request containing abort (might be NULL) */ static inline -void zfcp_dbf_scsi_abort(const char *tag, struct zfcp_dbf *dbf, - struct scsi_cmnd *scmd, struct zfcp_fsf_req *new_req, - unsigned long old_id) +void zfcp_dbf_scsi_abort(char *tag, struct scsi_cmnd *scmd, + struct zfcp_fsf_req *fsf_req) { - zfcp_dbf_scsi("abrt", tag, 1, dbf, scmd, new_req, old_id); + _zfcp_dbf_scsi(tag, 1, scmd, fsf_req); } /** @@ -347,12 +351,17 @@ void zfcp_dbf_scsi_abort(const char *tag, struct zfcp_dbf *dbf, * @flag: indicates type of reset (Target Reset, Logical Unit Reset) */ static inline -void zfcp_dbf_scsi_devreset(const char *tag, struct scsi_cmnd *scmnd, u8 flag) +void zfcp_dbf_scsi_devreset(char *tag, struct scsi_cmnd *scmnd, u8 flag) { - struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scmnd->device); + char tmp_tag[ZFCP_DBF_TAG_LEN]; + + if (flag == FCP_TMF_TGT_RESET) + memcpy(tmp_tag, "tr_", 3); + else + memcpy(tmp_tag, "lr_", 3); - zfcp_dbf_scsi(flag == FCP_TMF_TGT_RESET ? "trst" : "lrst", tag, 1, - zfcp_sdev->port->adapter->dbf, scmnd, NULL, 0); + memcpy(&tmp_tag[3], tag, 4); + _zfcp_dbf_scsi(tmp_tag, 1, scmnd, NULL); } #endif /* ZFCP_DBF_H */ diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 00875de2cb99..b68a546275a5 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -56,9 +56,7 @@ extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *); extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32); extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *); -extern void _zfcp_dbf_scsi(const char *, const char *, int, struct zfcp_dbf *, - struct scsi_cmnd *, struct zfcp_fsf_req *, - unsigned long); +extern void zfcp_dbf_scsi(char *, struct scsi_cmnd *, struct zfcp_fsf_req *); /* zfcp_erp.c */ extern void zfcp_erp_set_adapter_status(struct zfcp_adapter *, u32); diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 9881ba947f11..5bb118e01f36 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -2105,7 +2105,7 @@ static void zfcp_fsf_fcp_cmnd_handler(struct zfcp_fsf_req *req) skip_fsfstatus: zfcp_fsf_req_trace(req, scpnt); - zfcp_dbf_scsi_result(req->adapter->dbf, scpnt, req); + zfcp_dbf_scsi_result(scpnt, req); scpnt->host_scribble = NULL; (scpnt->scsi_done) (scpnt); diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 63529ed801eb..8c5c1c89c098 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -68,11 +68,8 @@ static int zfcp_scsi_slave_configure(struct scsi_device *sdp) static void zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result) { - struct zfcp_adapter *adapter = - (struct zfcp_adapter *) scpnt->device->host->hostdata[0]; - set_host_byte(scpnt, result); - zfcp_dbf_scsi_fail_send(adapter->dbf, scpnt); + zfcp_dbf_scsi_fail_send(scpnt); scpnt->scsi_done(scpnt); } @@ -80,7 +77,6 @@ static int zfcp_scsi_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scpnt) { struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device); - struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; struct fc_rport *rport = starget_to_rport(scsi_target(scpnt->device)); int status, scsi_result, ret; @@ -91,7 +87,7 @@ int zfcp_scsi_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scpnt) scsi_result = fc_remote_port_chkready(rport); if (unlikely(scsi_result)) { scpnt->result = scsi_result; - zfcp_dbf_scsi_fail_send(adapter->dbf, scpnt); + zfcp_dbf_scsi_fail_send(scpnt); scpnt->scsi_done(scpnt); return 0; } @@ -182,8 +178,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) old_req = zfcp_reqlist_find(adapter->req_list, old_reqid); if (!old_req) { write_unlock_irqrestore(&adapter->abort_lock, flags); - zfcp_dbf_scsi_abort("lte1", adapter->dbf, scpnt, NULL, - old_reqid); + zfcp_dbf_scsi_abort("abrt_or", scpnt, NULL); return FAILED; /* completion could be in progress */ } old_req->data = NULL; @@ -198,29 +193,32 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) zfcp_erp_wait(adapter); ret = fc_block_scsi_eh(scpnt); - if (ret) + if (ret) { + zfcp_dbf_scsi_abort("abrt_bl", scpnt, NULL); return ret; + } if (!(atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_RUNNING)) { - zfcp_dbf_scsi_abort("nres", adapter->dbf, scpnt, NULL, - old_reqid); + zfcp_dbf_scsi_abort("abrt_ru", scpnt, NULL); return SUCCESS; } } - if (!abrt_req) + if (!abrt_req) { + zfcp_dbf_scsi_abort("abrt_ar", scpnt, NULL); return FAILED; + } wait_for_completion(&abrt_req->completion); if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) - dbf_tag = "okay"; + dbf_tag = "abrt_ok"; else if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) - dbf_tag = "lte2"; + dbf_tag = "abrt_nn"; else { - dbf_tag = "fail"; + dbf_tag = "abrt_fa"; retval = FAILED; } - zfcp_dbf_scsi_abort(dbf_tag, adapter->dbf, scpnt, abrt_req, old_reqid); + zfcp_dbf_scsi_abort(dbf_tag, scpnt, abrt_req); zfcp_fsf_req_free(abrt_req); return retval; } -- cgit v1.2.3-59-g8ed1b From ea4a3a6ac40e2a585654808d4aefb39a6d57dca0 Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Thu, 2 Dec 2010 15:16:16 +0100 Subject: [SCSI] zfcp: Redesign of the debug tracing final cleanup. This patch is the final cleanup of the redesign from the zfcp tracing. Structures and elements which were used by multiple areas of the former debug tracing are now changed to the new scheme. Signed-off-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_aux.c | 5 +-- drivers/s390/scsi/zfcp_ccw.c | 14 +++--- drivers/s390/scsi/zfcp_cfdc.c | 8 ++-- drivers/s390/scsi/zfcp_dbf.c | 70 +++++++++++++++--------------- drivers/s390/scsi/zfcp_dbf.h | 25 ++++++++--- drivers/s390/scsi/zfcp_erp.c | 97 ++++++++++++++++++++---------------------- drivers/s390/scsi/zfcp_ext.h | 18 ++++---- drivers/s390/scsi/zfcp_fc.c | 18 ++++---- drivers/s390/scsi/zfcp_fsf.c | 85 +++++++++++++++++------------------- drivers/s390/scsi/zfcp_qdio.c | 6 +-- drivers/s390/scsi/zfcp_scsi.c | 6 +-- drivers/s390/scsi/zfcp_sysfs.c | 9 ++-- 12 files changed, 180 insertions(+), 181 deletions(-) diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 044fb22718d2..352ca0d4ca25 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -311,8 +311,7 @@ int zfcp_status_read_refill(struct zfcp_adapter *adapter) if (zfcp_fsf_status_read(adapter->qdio)) { if (atomic_read(&adapter->stat_miss) >= adapter->stat_read_buf_num) { - zfcp_erp_adapter_reopen(adapter, 0, "axsref1", - NULL); + zfcp_erp_adapter_reopen(adapter, 0, "axsref1"); return 1; } break; @@ -459,7 +458,7 @@ void zfcp_adapter_unregister(struct zfcp_adapter *adapter) sysfs_remove_group(&cdev->dev.kobj, &zfcp_sysfs_adapter_attrs); zfcp_erp_thread_kill(adapter); - zfcp_dbf_adapter_unregister(adapter->dbf); + zfcp_dbf_adapter_unregister(adapter); zfcp_qdio_destroy(adapter->qdio); zfcp_ccw_adapter_put(adapter); /* final put to release */ diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 0833c2b51e39..4f7852dd30c7 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c @@ -48,7 +48,7 @@ static int zfcp_ccw_activate(struct ccw_device *cdev) zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING); zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, - "ccresu2", NULL); + "ccresu2"); zfcp_erp_wait(adapter); flush_work(&adapter->scan_work); @@ -182,7 +182,7 @@ static int zfcp_ccw_set_offline(struct ccw_device *cdev) if (!adapter) return 0; - zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1", NULL); + zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1"); zfcp_erp_wait(adapter); zfcp_ccw_adapter_put(adapter); @@ -207,24 +207,24 @@ static int zfcp_ccw_notify(struct ccw_device *cdev, int event) switch (event) { case CIO_GONE: dev_warn(&cdev->dev, "The FCP device has been detached\n"); - zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1", NULL); + zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1"); break; case CIO_NO_PATH: dev_warn(&cdev->dev, "The CHPID for the FCP device is offline\n"); - zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2", NULL); + zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2"); break; case CIO_OPER: dev_info(&cdev->dev, "The FCP device is operational again\n"); zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING); zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, - "ccnoti4", NULL); + "ccnoti4"); break; case CIO_BOXED: dev_warn(&cdev->dev, "The FCP device did not respond within " "the specified time\n"); - zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti5", NULL); + zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti5"); break; } @@ -243,7 +243,7 @@ static void zfcp_ccw_shutdown(struct ccw_device *cdev) if (!adapter) return; - zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1", NULL); + zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1"); zfcp_erp_wait(adapter); zfcp_erp_thread_kill(adapter); diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c index d692e229ecba..46342fee394d 100644 --- a/drivers/s390/scsi/zfcp_cfdc.c +++ b/drivers/s390/scsi/zfcp_cfdc.c @@ -288,7 +288,7 @@ void zfcp_cfdc_adapter_access_changed(struct zfcp_adapter *adapter) (status & ZFCP_STATUS_COMMON_ACCESS_BOXED)) zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, - "cfaac_1", NULL); + "cfaac_1"); } read_unlock_irqrestore(&adapter->port_list_lock, flags); @@ -299,7 +299,7 @@ void zfcp_cfdc_adapter_access_changed(struct zfcp_adapter *adapter) (status & ZFCP_STATUS_COMMON_ACCESS_BOXED)) zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED, - "cfaac_2", NULL); + "cfaac_2"); } } @@ -426,7 +426,7 @@ int zfcp_cfdc_open_lun_eval(struct scsi_device *sdev, zfcp_scsi_dev_lun(sdev), (unsigned long long)zfcp_sdev->port->wwpn); zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED); - zfcp_erp_lun_shutdown(sdev, 0, "fsouh_6", NULL); + zfcp_erp_lun_shutdown(sdev, 0, "fsouh_6"); return -EACCES; } @@ -437,7 +437,7 @@ int zfcp_cfdc_open_lun_eval(struct scsi_device *sdev, zfcp_scsi_dev_lun(sdev), (unsigned long long)zfcp_sdev->port->wwpn); zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED); - zfcp_erp_lun_shutdown(sdev, 0, "fsosh_8", NULL); + zfcp_erp_lun_shutdown(sdev, 0, "fsosh_8"); return -EACCES; } diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index f9bd094c6e63..96d1462e0bf5 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -377,26 +377,37 @@ void zfcp_dbf_scsi(char *tag, struct scsi_cmnd *sc, struct zfcp_fsf_req *fsf) } } - debug_event(adapter->dbf->scsi, 1, rec, sizeof(*rec)); + debug_event(dbf->scsi, 1, rec, sizeof(*rec)); spin_unlock_irqrestore(&dbf->scsi_lock, flags); } -static debug_info_t *zfcp_dbf_reg(const char *name, int level, - struct debug_view *view, int size) +static debug_info_t *zfcp_dbf_reg(const char *name, int size, int rec_size) { struct debug_info *d; - d = debug_register(name, dbfsize, level, size); + d = debug_register(name, size, 1, rec_size); if (!d) return NULL; debug_register_view(d, &debug_hex_ascii_view); - debug_register_view(d, view); - debug_set_level(d, level); + debug_set_level(d, 3); return d; } +static void zfcp_dbf_unregister(struct zfcp_dbf *dbf) +{ + if (!dbf) + return; + + debug_unregister(dbf->scsi); + debug_unregister(dbf->san); + debug_unregister(dbf->hba); + debug_unregister(dbf->pay); + debug_unregister(dbf->rec); + kfree(dbf); +} + /** * zfcp_adapter_debug_register - registers debug feature for an adapter * @adapter: pointer to adapter for which debug features should be registered @@ -404,15 +415,13 @@ static debug_info_t *zfcp_dbf_reg(const char *name, int level, */ int zfcp_dbf_adapter_register(struct zfcp_adapter *adapter) { - char dbf_name[DEBUG_MAX_NAME_LEN]; + char name[DEBUG_MAX_NAME_LEN]; struct zfcp_dbf *dbf; dbf = kzalloc(sizeof(struct zfcp_dbf), GFP_KERNEL); if (!dbf) return -ENOMEM; - dbf->adapter = adapter; - spin_lock_init(&dbf->pay_lock); spin_lock_init(&dbf->hba_lock); spin_lock_init(&dbf->san_lock); @@ -420,59 +429,52 @@ int zfcp_dbf_adapter_register(struct zfcp_adapter *adapter) spin_lock_init(&dbf->rec_lock); /* debug feature area which records recovery activity */ - sprintf(dbf_name, "zfcp_%s_rec", dev_name(&adapter->ccw_device->dev)); - dbf->rec = zfcp_dbf_reg(dbf_name, 3, NULL, sizeof(struct zfcp_dbf_rec)); + sprintf(name, "zfcp_%s_rec", dev_name(&adapter->ccw_device->dev)); + dbf->rec = zfcp_dbf_reg(name, dbfsize, sizeof(struct zfcp_dbf_rec)); if (!dbf->rec) goto err_out; /* debug feature area which records HBA (FSF and QDIO) conditions */ - sprintf(dbf_name, "zfcp_%s_hba", dev_name(&adapter->ccw_device->dev)); - dbf->hba = zfcp_dbf_reg(dbf_name, 3, NULL, sizeof(struct zfcp_dbf_hba)); + sprintf(name, "zfcp_%s_hba", dev_name(&adapter->ccw_device->dev)); + dbf->hba = zfcp_dbf_reg(name, dbfsize, sizeof(struct zfcp_dbf_hba)); if (!dbf->hba) goto err_out; /* debug feature area which records payload info */ - sprintf(dbf_name, "zfcp_%s_pay", dev_name(&adapter->ccw_device->dev)); - dbf->pay = zfcp_dbf_reg(dbf_name, 3, NULL, - sizeof(struct zfcp_dbf_pay)); + sprintf(name, "zfcp_%s_pay", dev_name(&adapter->ccw_device->dev)); + dbf->pay = zfcp_dbf_reg(name, dbfsize * 2, sizeof(struct zfcp_dbf_pay)); if (!dbf->pay) goto err_out; /* debug feature area which records SAN command failures and recovery */ - sprintf(dbf_name, "zfcp_%s_san", dev_name(&adapter->ccw_device->dev)); - dbf->san = zfcp_dbf_reg(dbf_name, 3, NULL, sizeof(struct zfcp_dbf_san)); + sprintf(name, "zfcp_%s_san", dev_name(&adapter->ccw_device->dev)); + dbf->san = zfcp_dbf_reg(name, dbfsize, sizeof(struct zfcp_dbf_san)); if (!dbf->san) goto err_out; /* debug feature area which records SCSI command failures and recovery */ - sprintf(dbf_name, "zfcp_%s_scsi", dev_name(&adapter->ccw_device->dev)); - dbf->scsi = zfcp_dbf_reg(dbf_name, 3, NULL, - sizeof(struct zfcp_dbf_scsi)); + sprintf(name, "zfcp_%s_scsi", dev_name(&adapter->ccw_device->dev)); + dbf->scsi = zfcp_dbf_reg(name, dbfsize, sizeof(struct zfcp_dbf_scsi)); if (!dbf->scsi) goto err_out; adapter->dbf = dbf; - return 0; + return 0; err_out: - zfcp_dbf_adapter_unregister(dbf); + zfcp_dbf_unregister(dbf); return -ENOMEM; } /** * zfcp_adapter_debug_unregister - unregisters debug feature for an adapter - * @dbf: pointer to dbf for which debug features should be unregistered + * @adapter: pointer to adapter for which debug features should be unregistered */ -void zfcp_dbf_adapter_unregister(struct zfcp_dbf *dbf) +void zfcp_dbf_adapter_unregister(struct zfcp_adapter *adapter) { - if (!dbf) - return; - debug_unregister(dbf->scsi); - debug_unregister(dbf->san); - debug_unregister(dbf->hba); - debug_unregister(dbf->pay); - debug_unregister(dbf->rec); - dbf->adapter->dbf = NULL; - kfree(dbf); + struct zfcp_dbf *dbf = adapter->dbf; + + adapter->dbf = NULL; + zfcp_dbf_unregister(dbf); } diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h index 2cee8197dd02..714f087eb7a9 100644 --- a/drivers/s390/scsi/zfcp_dbf.h +++ b/drivers/s390/scsi/zfcp_dbf.h @@ -14,8 +14,6 @@ #include "zfcp_def.h" #define ZFCP_DBF_TAG_LEN 7 -#define ZFCP_DBF_TAG_SIZE 4 -#define ZFCP_DBF_ID_SIZE 7 #define ZFCP_DBF_INVALID_LUN 0xFFFFFFFFFFFFFFFFull @@ -233,13 +231,31 @@ struct zfcp_dbf_scsi { * @data: unformatted data */ struct zfcp_dbf_pay { + u8 counter; char area[ZFCP_DBF_TAG_LEN]; - char counter; u64 fsf_req_id; #define ZFCP_DBF_PAY_MAX_REC 0x100 char data[ZFCP_DBF_PAY_MAX_REC]; } __packed; +/** + * struct zfcp_dbf - main dbf trace structure + * @pay: reference to payload trace area + * @rec: reference to recovery trace area + * @hba: reference to hba trace area + * @san: reference to san trace area + * @scsi: reference to scsi trace area + * @pay_lock: lock protecting payload trace buffer + * @rec_lock: lock protecting recovery trace buffer + * @hba_lock: lock protecting hba trace buffer + * @san_lock: lock protecting san trace buffer + * @scsi_lock: lock protecting scsi trace buffer + * @pay_buf: pre-allocated buffer for payload + * @rec_buf: pre-allocated buffer for recovery + * @hba_buf: pre-allocated buffer for hba + * @san_buf: pre-allocated buffer for san + * @scsi_buf: pre-allocated buffer for scsi + */ struct zfcp_dbf { debug_info_t *pay; debug_info_t *rec; @@ -251,12 +267,11 @@ struct zfcp_dbf { spinlock_t hba_lock; spinlock_t san_lock; spinlock_t scsi_lock; + struct zfcp_dbf_pay pay_buf; struct zfcp_dbf_rec rec_buf; struct zfcp_dbf_hba hba_buf; struct zfcp_dbf_san san_buf; struct zfcp_dbf_scsi scsi_buf; - struct zfcp_dbf_pay pay_buf; - struct zfcp_adapter *adapter; }; static inline diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 62b1b4a03ee3..066f9ea67502 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -236,7 +236,7 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status, static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, struct zfcp_port *port, struct scsi_device *sdev, - char *id, void *ref, u32 act_status) + char *id, u32 act_status) { int retval = 1, need; struct zfcp_erp_action *act; @@ -262,7 +262,7 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, } static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, - int clear_mask, char *id, void *ref) + int clear_mask, char *id) { zfcp_erp_adapter_block(adapter, clear_mask); zfcp_scsi_schedule_rports_block(adapter); @@ -274,7 +274,7 @@ static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, return -EIO; } return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, - adapter, NULL, NULL, id, ref, 0); + adapter, NULL, NULL, id, 0); } /** @@ -282,10 +282,8 @@ static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, * @adapter: Adapter to reopen. * @clear: Status flags to clear. * @id: Id for debug trace event. - * @ref: Reference for debug trace event. */ -void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, - char *id, void *ref) +void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, char *id) { unsigned long flags; @@ -298,7 +296,7 @@ void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, ZFCP_STATUS_COMMON_ERP_FAILED); else zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter, - NULL, NULL, id, ref, 0); + NULL, NULL, id, 0); write_unlock_irqrestore(&adapter->erp_lock, flags); } @@ -307,13 +305,12 @@ void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, * @adapter: Adapter to shut down. * @clear: Status flags to clear. * @id: Id for debug trace event. - * @ref: Reference for debug trace event. */ void zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear, - char *id, void *ref) + char *id) { int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; - zfcp_erp_adapter_reopen(adapter, clear | flags, id, ref); + zfcp_erp_adapter_reopen(adapter, clear | flags, id); } /** @@ -321,13 +318,11 @@ void zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear, * @port: Port to shut down. * @clear: Status flags to clear. * @id: Id for debug trace event. - * @ref: Reference for debug trace event. */ -void zfcp_erp_port_shutdown(struct zfcp_port *port, int clear, char *id, - void *ref) +void zfcp_erp_port_shutdown(struct zfcp_port *port, int clear, char *id) { int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; - zfcp_erp_port_reopen(port, clear | flags, id, ref); + zfcp_erp_port_reopen(port, clear | flags, id); } static void zfcp_erp_port_block(struct zfcp_port *port, int clear) @@ -336,8 +331,8 @@ static void zfcp_erp_port_block(struct zfcp_port *port, int clear) ZFCP_STATUS_COMMON_UNBLOCKED | clear); } -static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, - int clear, char *id, void *ref) +static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, + char *id) { zfcp_erp_port_block(port, clear); zfcp_scsi_schedule_rport_block(port); @@ -346,28 +341,26 @@ static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, return; zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED, - port->adapter, port, NULL, id, ref, 0); + port->adapter, port, NULL, id, 0); } /** * zfcp_erp_port_forced_reopen - Forced close of port and open again * @port: Port to force close and to reopen. + * @clear: Status flags to clear. * @id: Id for debug trace event. - * @ref: Reference for debug trace event. */ -void zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, char *id, - void *ref) +void zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, char *id) { unsigned long flags; struct zfcp_adapter *adapter = port->adapter; write_lock_irqsave(&adapter->erp_lock, flags); - _zfcp_erp_port_forced_reopen(port, clear, id, ref); + _zfcp_erp_port_forced_reopen(port, clear, id); write_unlock_irqrestore(&adapter->erp_lock, flags); } -static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, - void *ref) +static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id) { zfcp_erp_port_block(port, clear); zfcp_scsi_schedule_rport_block(port); @@ -379,24 +372,25 @@ static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, } return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT, - port->adapter, port, NULL, id, ref, 0); + port->adapter, port, NULL, id, 0); } /** * zfcp_erp_port_reopen - trigger remote port recovery * @port: port to recover * @clear_mask: flags in port status to be cleared + * @id: Id for debug trace event. * * Returns 0 if recovery has been triggered, < 0 if not. */ -int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, void *ref) +int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id) { int retval; unsigned long flags; struct zfcp_adapter *adapter = port->adapter; write_lock_irqsave(&adapter->erp_lock, flags); - retval = _zfcp_erp_port_reopen(port, clear, id, ref); + retval = _zfcp_erp_port_reopen(port, clear, id); write_unlock_irqrestore(&adapter->erp_lock, flags); return retval; @@ -409,7 +403,7 @@ static void zfcp_erp_lun_block(struct scsi_device *sdev, int clear_mask) } static void _zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id, - void *ref, u32 act_status) + u32 act_status) { struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; @@ -420,17 +414,18 @@ static void _zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id, return; zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_LUN, adapter, - zfcp_sdev->port, sdev, id, ref, act_status); + zfcp_sdev->port, sdev, id, act_status); } /** * zfcp_erp_lun_reopen - initiate reopen of a LUN * @sdev: SCSI device / LUN to be reopened * @clear_mask: specifies flags in LUN status to be cleared + * @id: Id for debug trace event. + * * Return: 0 on success, < 0 on error */ -void zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id, - void *ref) +void zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id) { unsigned long flags; struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); @@ -438,7 +433,7 @@ void zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id, struct zfcp_adapter *adapter = port->adapter; write_lock_irqsave(&adapter->erp_lock, flags); - _zfcp_erp_lun_reopen(sdev, clear, id, ref, 0); + _zfcp_erp_lun_reopen(sdev, clear, id, 0); write_unlock_irqrestore(&adapter->erp_lock, flags); } @@ -447,13 +442,11 @@ void zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id, * @sdev: SCSI device / LUN to shut down. * @clear: Status flags to clear. * @id: Id for debug trace event. - * @ref: Reference for debug trace event. */ -void zfcp_erp_lun_shutdown(struct scsi_device *sdev, int clear, char *id, - void *ref) +void zfcp_erp_lun_shutdown(struct scsi_device *sdev, int clear, char *id) { int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; - zfcp_erp_lun_reopen(sdev, clear | flags, id, ref); + zfcp_erp_lun_reopen(sdev, clear | flags, id); } /** @@ -475,7 +468,7 @@ void zfcp_erp_lun_shutdown_wait(struct scsi_device *sdev, char *id) int clear = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED; write_lock_irqsave(&adapter->erp_lock, flags); - _zfcp_erp_lun_reopen(sdev, clear, id, NULL, ZFCP_STATUS_ERP_NO_REF); + _zfcp_erp_lun_reopen(sdev, clear, id, ZFCP_STATUS_ERP_NO_REF); write_unlock_irqrestore(&adapter->erp_lock, flags); zfcp_erp_wait(adapter); @@ -584,40 +577,40 @@ static void zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action) } static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter, - int clear, char *id, void *ref) + int clear, char *id) { struct zfcp_port *port; read_lock(&adapter->port_list_lock); list_for_each_entry(port, &adapter->port_list, list) - _zfcp_erp_port_reopen(port, clear, id, ref); + _zfcp_erp_port_reopen(port, clear, id); read_unlock(&adapter->port_list_lock); } static void _zfcp_erp_lun_reopen_all(struct zfcp_port *port, int clear, - char *id, void *ref) + char *id) { struct scsi_device *sdev; shost_for_each_device(sdev, port->adapter->scsi_host) if (sdev_to_zfcp(sdev)->port == port) - _zfcp_erp_lun_reopen(sdev, clear, id, ref, 0); + _zfcp_erp_lun_reopen(sdev, clear, id, 0); } static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act) { switch (act->action) { case ZFCP_ERP_ACTION_REOPEN_ADAPTER: - _zfcp_erp_adapter_reopen(act->adapter, 0, "ersff_1", NULL); + _zfcp_erp_adapter_reopen(act->adapter, 0, "ersff_1"); break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: - _zfcp_erp_port_forced_reopen(act->port, 0, "ersff_2", NULL); + _zfcp_erp_port_forced_reopen(act->port, 0, "ersff_2"); break; case ZFCP_ERP_ACTION_REOPEN_PORT: - _zfcp_erp_port_reopen(act->port, 0, "ersff_3", NULL); + _zfcp_erp_port_reopen(act->port, 0, "ersff_3"); break; case ZFCP_ERP_ACTION_REOPEN_LUN: - _zfcp_erp_lun_reopen(act->sdev, 0, "ersff_4", NULL, 0); + _zfcp_erp_lun_reopen(act->sdev, 0, "ersff_4", 0); break; } } @@ -626,13 +619,13 @@ static void zfcp_erp_strategy_followup_success(struct zfcp_erp_action *act) { switch (act->action) { case ZFCP_ERP_ACTION_REOPEN_ADAPTER: - _zfcp_erp_port_reopen_all(act->adapter, 0, "ersfs_1", NULL); + _zfcp_erp_port_reopen_all(act->adapter, 0, "ersfs_1"); break; case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: - _zfcp_erp_port_reopen(act->port, 0, "ersfs_2", NULL); + _zfcp_erp_port_reopen(act->port, 0, "ersfs_2"); break; case ZFCP_ERP_ACTION_REOPEN_PORT: - _zfcp_erp_lun_reopen_all(act->port, 0, "ersfs_3", NULL); + _zfcp_erp_lun_reopen_all(act->port, 0, "ersfs_3"); break; } } @@ -669,7 +662,7 @@ static void zfcp_erp_enqueue_ptp_port(struct zfcp_adapter *adapter) adapter->peer_d_id); if (IS_ERR(port)) /* error or port already attached */ return; - _zfcp_erp_port_reopen(port, 0, "ereptp1", NULL); + _zfcp_erp_port_reopen(port, 0, "ereptp1"); } static int zfcp_erp_adapter_strat_fsf_xconf(struct zfcp_erp_action *erp_action) @@ -1163,7 +1156,7 @@ static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret) if (zfcp_erp_strat_change_det(&adapter->status, erp_status)) { _zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, - "ersscg1", NULL); + "ersscg1"); return ZFCP_ERP_EXIT; } break; @@ -1173,7 +1166,7 @@ static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret) if (zfcp_erp_strat_change_det(&port->status, erp_status)) { _zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, - "ersscg2", NULL); + "ersscg2"); return ZFCP_ERP_EXIT; } break; @@ -1183,7 +1176,7 @@ static int zfcp_erp_strategy_statechange(struct zfcp_erp_action *act, int ret) if (zfcp_erp_strat_change_det(&zfcp_sdev->status, erp_status)) { _zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED, - "ersscg3", NULL, 0); + "ersscg3", 0); return ZFCP_ERP_EXIT; } break; @@ -1310,7 +1303,7 @@ static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action) erp_action->status |= ZFCP_STATUS_ERP_LOWMEM; } if (adapter->erp_total_count == adapter->erp_low_mem_count) - _zfcp_erp_adapter_reopen(adapter, 0, "erstgy1", NULL); + _zfcp_erp_adapter_reopen(adapter, 0, "erstgy1"); else { zfcp_erp_strategy_memwait(erp_action); retval = ZFCP_ERP_CONTINUES; diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index b68a546275a5..6e325284fbe7 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -45,7 +45,7 @@ extern void zfcp_cfdc_adapter_access_changed(struct zfcp_adapter *); /* zfcp_dbf.c */ extern int zfcp_dbf_adapter_register(struct zfcp_adapter *); -extern void zfcp_dbf_adapter_unregister(struct zfcp_dbf *); +extern void zfcp_dbf_adapter_unregister(struct zfcp_adapter *); extern void zfcp_dbf_rec_trig(char *, struct zfcp_adapter *, struct zfcp_port *, struct scsi_device *, u8, u8); extern void zfcp_dbf_rec_run(char *, struct zfcp_erp_action *); @@ -61,19 +61,17 @@ extern void zfcp_dbf_scsi(char *, struct scsi_cmnd *, struct zfcp_fsf_req *); /* zfcp_erp.c */ extern void zfcp_erp_set_adapter_status(struct zfcp_adapter *, u32); extern void zfcp_erp_clear_adapter_status(struct zfcp_adapter *, u32); -extern void zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, char *, void *); -extern void zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, char *, - void *); +extern void zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, char *); +extern void zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, char *); extern void zfcp_erp_set_port_status(struct zfcp_port *, u32); extern void zfcp_erp_clear_port_status(struct zfcp_port *, u32); -extern int zfcp_erp_port_reopen(struct zfcp_port *, int, char *, void *); -extern void zfcp_erp_port_shutdown(struct zfcp_port *, int, char *, void *); -extern void zfcp_erp_port_forced_reopen(struct zfcp_port *, int, char *, - void *); +extern int zfcp_erp_port_reopen(struct zfcp_port *, int, char *); +extern void zfcp_erp_port_shutdown(struct zfcp_port *, int, char *); +extern void zfcp_erp_port_forced_reopen(struct zfcp_port *, int, char *); extern void zfcp_erp_set_lun_status(struct scsi_device *, u32); extern void zfcp_erp_clear_lun_status(struct scsi_device *, u32); -extern void zfcp_erp_lun_reopen(struct scsi_device *, int, char *, void *); -extern void zfcp_erp_lun_shutdown(struct scsi_device *, int, char *, void *); +extern void zfcp_erp_lun_reopen(struct scsi_device *, int, char *); +extern void zfcp_erp_lun_shutdown(struct scsi_device *, int, char *); extern void zfcp_erp_lun_shutdown_wait(struct scsi_device *, char *); extern int zfcp_erp_thread_setup(struct zfcp_adapter *); extern void zfcp_erp_thread_kill(struct zfcp_adapter *); diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 7d44d9c59bdc..30cf91a787a3 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -174,7 +174,7 @@ static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, if (!port->d_id) zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, - "fcrscn1", NULL); + "fcrscn1"); } read_unlock_irqrestore(&adapter->port_list_lock, flags); } @@ -215,7 +215,7 @@ static void zfcp_fc_incoming_wwpn(struct zfcp_fsf_req *req, u64 wwpn) read_lock_irqsave(&adapter->port_list_lock, flags); list_for_each_entry(port, &adapter->port_list, list) if (port->wwpn == wwpn) { - zfcp_erp_port_forced_reopen(port, 0, "fciwwp1", req); + zfcp_erp_port_forced_reopen(port, 0, "fciwwp1"); break; } read_unlock_irqrestore(&adapter->port_list_lock, flags); @@ -360,7 +360,7 @@ void zfcp_fc_port_did_lookup(struct work_struct *work) ret = zfcp_fc_ns_gid_pn(port); if (ret) { /* could not issue gid_pn for some reason */ - zfcp_erp_adapter_reopen(port->adapter, 0, "fcgpn_1", NULL); + zfcp_erp_adapter_reopen(port->adapter, 0, "fcgpn_1"); goto out; } @@ -369,7 +369,7 @@ void zfcp_fc_port_did_lookup(struct work_struct *work) goto out; } - zfcp_erp_port_reopen(port, 0, "fcgpn_3", NULL); + zfcp_erp_port_reopen(port, 0, "fcgpn_3"); out: put_device(&port->dev); } @@ -426,7 +426,7 @@ static void zfcp_fc_adisc_handler(void *data) if (adisc->els.status) { /* request rejected or timed out */ zfcp_erp_port_forced_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, - "fcadh_1", NULL); + "fcadh_1"); goto out; } @@ -436,7 +436,7 @@ static void zfcp_fc_adisc_handler(void *data) if ((port->wwpn != adisc_resp->adisc_wwpn) || !(atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN)) { zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, - "fcadh_2", NULL); + "fcadh_2"); goto out; } @@ -507,7 +507,7 @@ void zfcp_fc_link_test_work(struct work_struct *work) /* send of ADISC was not possible */ atomic_clear_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status); - zfcp_erp_port_forced_reopen(port, 0, "fcltwk1", NULL); + zfcp_erp_port_forced_reopen(port, 0, "fcltwk1"); out: put_device(&port->dev); @@ -659,7 +659,7 @@ static int zfcp_fc_eval_gpn_ft(struct zfcp_fc_gpn_ft *gpn_ft, port = zfcp_port_enqueue(adapter, acc->fp_wwpn, ZFCP_STATUS_COMMON_NOESC, d_id); if (!IS_ERR(port)) - zfcp_erp_port_reopen(port, 0, "fcegpf1", NULL); + zfcp_erp_port_reopen(port, 0, "fcegpf1"); else if (PTR_ERR(port) != -EEXIST) ret = PTR_ERR(port); } @@ -671,7 +671,7 @@ static int zfcp_fc_eval_gpn_ft(struct zfcp_fc_gpn_ft *gpn_ft, write_unlock_irqrestore(&adapter->port_list_lock, flags); list_for_each_entry_safe(port, tmp, &remove_lh, list) { - zfcp_erp_port_shutdown(port, 0, "fcegpf2", NULL); + zfcp_erp_port_shutdown(port, 0, "fcegpf2"); zfcp_device_unregister(&port->dev, &zfcp_sysfs_port_attrs); } diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 5bb118e01f36..60ff9d172c79 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -23,7 +23,7 @@ static void zfcp_fsf_request_timeout_handler(unsigned long data) struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; zfcp_qdio_siosl(adapter); zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, - "fsrth_1", NULL); + "fsrth_1"); } static void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, @@ -65,7 +65,7 @@ static void zfcp_fsf_class_not_supp(struct zfcp_fsf_req *req) { dev_err(&req->adapter->ccw_device->dev, "FCP device not " "operational because of an unsupported FC class\n"); - zfcp_erp_adapter_shutdown(req->adapter, 0, "fscns_1", req); + zfcp_erp_adapter_shutdown(req->adapter, 0, "fscns_1"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; } @@ -98,7 +98,7 @@ static void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req) read_lock_irqsave(&adapter->port_list_lock, flags); list_for_each_entry(port, &adapter->port_list, list) if (port->d_id == d_id) { - zfcp_erp_port_reopen(port, 0, "fssrpc1", req); + zfcp_erp_port_reopen(port, 0, "fssrpc1"); break; } read_unlock_irqrestore(&adapter->port_list_lock, flags); @@ -247,7 +247,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req) zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | ZFCP_STATUS_COMMON_ERP_FAILED, - "fssrh_2", req); + "fssrh_2"); zfcp_fc_enqueue_event(adapter, FCH_EVT_LINKUP, 0); break; @@ -287,7 +287,7 @@ static void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req) "The FCP adapter reported a problem " "that cannot be recovered\n"); zfcp_qdio_siosl(req->adapter); - zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfsqe1", req); + zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfsqe1"); break; } /* all non-return stats set FSFREQ_ERROR*/ @@ -304,7 +304,7 @@ static void zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *req) dev_err(&req->adapter->ccw_device->dev, "The FCP adapter does not recognize the command 0x%x\n", req->qtcb->header.fsf_command); - zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfse_1", req); + zfcp_erp_adapter_shutdown(req->adapter, 0, "fsfse_1"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_ADAPTER_STATUS_AVAILABLE: @@ -335,17 +335,17 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req) "QTCB version 0x%x not supported by FCP adapter " "(0x%x to 0x%x)\n", FSF_QTCB_CURRENT_VERSION, psq->word[0], psq->word[1]); - zfcp_erp_adapter_shutdown(adapter, 0, "fspse_1", req); + zfcp_erp_adapter_shutdown(adapter, 0, "fspse_1"); break; case FSF_PROT_ERROR_STATE: case FSF_PROT_SEQ_NUMB_ERROR: - zfcp_erp_adapter_reopen(adapter, 0, "fspse_2", req); + zfcp_erp_adapter_reopen(adapter, 0, "fspse_2"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_PROT_UNSUPP_QTCB_TYPE: dev_err(&adapter->ccw_device->dev, "The QTCB type is not supported by the FCP adapter\n"); - zfcp_erp_adapter_shutdown(adapter, 0, "fspse_3", req); + zfcp_erp_adapter_shutdown(adapter, 0, "fspse_3"); break; case FSF_PROT_HOST_CONNECTION_INITIALIZING: atomic_set_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, @@ -355,12 +355,12 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req) dev_err(&adapter->ccw_device->dev, "0x%Lx is an ambiguous request identifier\n", (unsigned long long)qtcb->bottom.support.req_handle); - zfcp_erp_adapter_shutdown(adapter, 0, "fspse_4", req); + zfcp_erp_adapter_shutdown(adapter, 0, "fspse_4"); break; case FSF_PROT_LINK_DOWN: zfcp_fsf_link_down_info_eval(req, &psq->link_down_info); /* go through reopen to flush pending requests */ - zfcp_erp_adapter_reopen(adapter, 0, "fspse_6", req); + zfcp_erp_adapter_reopen(adapter, 0, "fspse_6"); break; case FSF_PROT_REEST_QUEUE: /* All ports should be marked as ready to run again */ @@ -369,14 +369,14 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req) zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | ZFCP_STATUS_COMMON_ERP_FAILED, - "fspse_8", req); + "fspse_8"); break; default: dev_err(&adapter->ccw_device->dev, "0x%x is not a valid transfer protocol status\n", qtcb->prefix.prot_status); zfcp_qdio_siosl(adapter); - zfcp_erp_adapter_shutdown(adapter, 0, "fspse_9", req); + zfcp_erp_adapter_shutdown(adapter, 0, "fspse_9"); } req->status |= ZFCP_STATUS_FSFREQ_ERROR; } @@ -482,7 +482,7 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) dev_err(&adapter->ccw_device->dev, "Unknown or unsupported arbitrated loop " "fibre channel topology detected\n"); - zfcp_erp_adapter_shutdown(adapter, 0, "fsece_1", req); + zfcp_erp_adapter_shutdown(adapter, 0, "fsece_1"); return -EIO; } @@ -518,7 +518,7 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) "FCP adapter maximum QTCB size (%d bytes) " "is too small\n", bottom->max_qtcb_size); - zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh1", req); + zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh1"); return; } atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, @@ -536,7 +536,7 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) &qtcb->header.fsf_status_qual.link_down_info); break; default: - zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh3", req); + zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh3"); return; } @@ -552,14 +552,14 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) dev_err(&adapter->ccw_device->dev, "The FCP adapter only supports newer " "control block versions\n"); - zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh4", req); + zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh4"); return; } if (FSF_QTCB_CURRENT_VERSION > bottom->high_qtcb_version) { dev_err(&adapter->ccw_device->dev, "The FCP adapter only supports older " "control block versions\n"); - zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh5", req); + zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh5"); } } @@ -700,7 +700,7 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) del_timer(&req->timer); /* lookup request again, list might have changed */ zfcp_reqlist_find_rm(adapter->req_list, req_id); - zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1", req); + zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1"); return -EIO; } @@ -777,14 +777,13 @@ static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req) case FSF_PORT_HANDLE_NOT_VALID: if (fsq->word[0] == fsq->word[1]) { zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, - "fsafch1", req); + "fsafch1"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; } break; case FSF_LUN_HANDLE_NOT_VALID: if (fsq->word[0] == fsq->word[1]) { - zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fsafch2", - req); + zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fsafch2"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; } break; @@ -795,14 +794,13 @@ static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req) zfcp_erp_set_port_status(zfcp_sdev->port, ZFCP_STATUS_COMMON_ACCESS_BOXED); zfcp_erp_port_reopen(zfcp_sdev->port, - ZFCP_STATUS_COMMON_ERP_FAILED, "fsafch3", - req); + ZFCP_STATUS_COMMON_ERP_FAILED, "fsafch3"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_LUN_BOXED: zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ACCESS_BOXED); zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED, - "fsafch4", req); + "fsafch4"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_ADAPTER_STATUS_AVAILABLE: @@ -903,7 +901,7 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req) req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_PORT_HANDLE_NOT_VALID: - zfcp_erp_adapter_reopen(adapter, 0, "fsscth1", req); + zfcp_erp_adapter_reopen(adapter, 0, "fsscth1"); /* fall through */ case FSF_GENERIC_COMMAND_REJECTED: case FSF_PAYLOAD_SIZE_MISMATCH: @@ -1449,7 +1447,7 @@ static void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req) switch (req->qtcb->header.fsf_status) { case FSF_PORT_HANDLE_NOT_VALID: - zfcp_erp_adapter_reopen(port->adapter, 0, "fscph_1", req); + zfcp_erp_adapter_reopen(port->adapter, 0, "fscph_1"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_ADAPTER_STATUS_AVAILABLE: @@ -1581,7 +1579,7 @@ static void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req) if (req->qtcb->header.fsf_status == FSF_PORT_HANDLE_NOT_VALID) { req->status |= ZFCP_STATUS_FSFREQ_ERROR; - zfcp_erp_adapter_reopen(wka_port->adapter, 0, "fscwph1", req); + zfcp_erp_adapter_reopen(wka_port->adapter, 0, "fscwph1"); } wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE; @@ -1639,7 +1637,7 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req) switch (header->fsf_status) { case FSF_PORT_HANDLE_NOT_VALID: - zfcp_erp_adapter_reopen(port->adapter, 0, "fscpph1", req); + zfcp_erp_adapter_reopen(port->adapter, 0, "fscpph1"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_ACCESS_DENIED: @@ -1655,7 +1653,7 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req) &sdev_to_zfcp(sdev)->status); zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ACCESS_BOXED); zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, - "fscpph2", req); + "fscpph2"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_ADAPTER_STATUS_AVAILABLE: @@ -1744,7 +1742,7 @@ static void zfcp_fsf_open_lun_handler(struct zfcp_fsf_req *req) switch (header->fsf_status) { case FSF_PORT_HANDLE_NOT_VALID: - zfcp_erp_adapter_reopen(adapter, 0, "fsouh_1", req); + zfcp_erp_adapter_reopen(adapter, 0, "fsouh_1"); /* fall through */ case FSF_LUN_ALREADY_OPEN: break; @@ -1756,8 +1754,7 @@ static void zfcp_fsf_open_lun_handler(struct zfcp_fsf_req *req) zfcp_erp_set_port_status(zfcp_sdev->port, ZFCP_STATUS_COMMON_ACCESS_BOXED); zfcp_erp_port_reopen(zfcp_sdev->port, - ZFCP_STATUS_COMMON_ERP_FAILED, "fsouh_2", - req); + ZFCP_STATUS_COMMON_ERP_FAILED, "fsouh_2"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_LUN_SHARING_VIOLATION: @@ -1853,20 +1850,18 @@ static void zfcp_fsf_close_lun_handler(struct zfcp_fsf_req *req) switch (req->qtcb->header.fsf_status) { case FSF_PORT_HANDLE_NOT_VALID: - zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fscuh_1", - req); + zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fscuh_1"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_LUN_HANDLE_NOT_VALID: - zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fscuh_2", req); + zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fscuh_2"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_PORT_BOXED: zfcp_erp_set_port_status(zfcp_sdev->port, ZFCP_STATUS_COMMON_ACCESS_BOXED); zfcp_erp_port_reopen(zfcp_sdev->port, - ZFCP_STATUS_COMMON_ERP_FAILED, "fscuh_3", - req); + ZFCP_STATUS_COMMON_ERP_FAILED, "fscuh_3"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_ADAPTER_STATUS_AVAILABLE: @@ -2003,13 +1998,12 @@ static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req) switch (header->fsf_status) { case FSF_HANDLE_MISMATCH: case FSF_PORT_HANDLE_NOT_VALID: - zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fssfch1", - req); + zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fssfch1"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_FCPLUN_NOT_VALID: case FSF_LUN_HANDLE_NOT_VALID: - zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fssfch2", req); + zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fssfch2"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_SERVICE_CLASS_NOT_SUPPORTED: @@ -2027,7 +2021,7 @@ static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req) (unsigned long long)zfcp_scsi_dev_lun(sdev), (unsigned long long)zfcp_sdev->port->wwpn); zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0, - "fssfch3", req); + "fssfch3"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_CMND_LENGTH_NOT_VALID: @@ -2038,21 +2032,20 @@ static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req) (unsigned long long)zfcp_scsi_dev_lun(sdev), (unsigned long long)zfcp_sdev->port->wwpn); zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0, - "fssfch4", req); + "fssfch4"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_PORT_BOXED: zfcp_erp_set_port_status(zfcp_sdev->port, ZFCP_STATUS_COMMON_ACCESS_BOXED); zfcp_erp_port_reopen(zfcp_sdev->port, - ZFCP_STATUS_COMMON_ERP_FAILED, "fssfch5", - req); + ZFCP_STATUS_COMMON_ERP_FAILED, "fssfch5"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_LUN_BOXED: zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ACCESS_BOXED); zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED, - "fssfch6", req); + "fssfch6"); req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_ADAPTER_STATUS_AVAILABLE: diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 434a33ba0509..d99c9dc9cfcb 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -41,7 +41,7 @@ static void zfcp_qdio_handler_error(struct zfcp_qdio *qdio, char *id, zfcp_qdio_siosl(adapter); zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | - ZFCP_STATUS_COMMON_ERP_FAILED, id, NULL); + ZFCP_STATUS_COMMON_ERP_FAILED, id); } static void zfcp_qdio_zero_sbals(struct qdio_buffer *sbal[], int first, int cnt) @@ -114,7 +114,7 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err, * put SBALs back to response queue */ if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, idx, count)) - zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdires2", NULL); + zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdires2"); } static struct qdio_buffer_element * @@ -234,7 +234,7 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio) if (!ret) { atomic_inc(&qdio->req_q_full); /* assume hanging outbound queue, try queue recovery */ - zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1", NULL); + zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1"); } spin_lock_irq(&qdio->req_q_lock); diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 8c5c1c89c098..59a653d15a19 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -154,7 +154,7 @@ static int zfcp_scsi_slave_alloc(struct scsi_device *sdev) spin_lock_init(&zfcp_sdev->latencies.lock); zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_RUNNING); - zfcp_erp_lun_reopen(sdev, 0, "scsla_1", NULL); + zfcp_erp_lun_reopen(sdev, 0, "scsla_1"); zfcp_erp_wait(port->adapter); return 0; @@ -278,7 +278,7 @@ static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; int ret; - zfcp_erp_adapter_reopen(adapter, 0, "schrh_1", scpnt); + zfcp_erp_adapter_reopen(adapter, 0, "schrh_1"); zfcp_erp_wait(adapter); ret = fc_block_scsi_eh(scpnt); if (ret) @@ -516,7 +516,7 @@ static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport) port = zfcp_get_port_by_wwpn(adapter, rport->port_name); if (port) { - zfcp_erp_port_forced_reopen(port, 0, "sctrpi1", NULL); + zfcp_erp_port_forced_reopen(port, 0, "sctrpi1"); put_device(&port->dev); } } diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index 2f2c54f4718f..cdc4ff78a7ba 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c @@ -105,8 +105,7 @@ static ssize_t zfcp_sysfs_port_failed_store(struct device *dev, return -EINVAL; zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_RUNNING); - zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, "sypfai2", - NULL); + zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, "sypfai2"); zfcp_erp_wait(port->adapter); return count; @@ -148,7 +147,7 @@ static ssize_t zfcp_sysfs_unit_failed_store(struct device *dev, if (sdev) { zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_RUNNING); zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED, - "syufai2", NULL); + "syufai2"); zfcp_erp_wait(unit->port->adapter); } else zfcp_unit_scsi_scan(unit); @@ -198,7 +197,7 @@ static ssize_t zfcp_sysfs_adapter_failed_store(struct device *dev, zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING); zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, - "syafai2", NULL); + "syafai2"); zfcp_erp_wait(adapter); out: zfcp_ccw_adapter_put(adapter); @@ -256,7 +255,7 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, put_device(&port->dev); - zfcp_erp_port_shutdown(port, 0, "syprs_1", NULL); + zfcp_erp_port_shutdown(port, 0, "syprs_1"); zfcp_device_unregister(&port->dev, &zfcp_sysfs_port_attrs); out: zfcp_ccw_adapter_put(adapter); -- cgit v1.2.3-59-g8ed1b From 3d63d3b4fb5fb3674f2d97725e187cbfa22562bc Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Thu, 2 Dec 2010 15:16:17 +0100 Subject: [SCSI] zfcp: Move qdio setup from erp to zfcp_qdio.c Initialization of the qdio waitqueue should happen when the qdio data is initialized and the QDIOUP flag should be handled in the qdio code as well. Adjust the code accordingly and remove the superfluos function zfcp_erp_adapter_strategy_open_qdio. Reviewed-by: Steffen Maier Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_erp.c | 13 +------------ drivers/s390/scsi/zfcp_qdio.c | 2 ++ 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 066f9ea67502..e003e306f870 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -644,17 +644,6 @@ static void zfcp_erp_wakeup(struct zfcp_adapter *adapter) read_unlock_irqrestore(&adapter->erp_lock, flags); } -static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *act) -{ - struct zfcp_qdio *qdio = act->adapter->qdio; - - if (zfcp_qdio_open(qdio)) - return ZFCP_ERP_FAILED; - init_waitqueue_head(&qdio->req_q_wq); - atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &act->adapter->status); - return ZFCP_ERP_SUCCEEDED; -} - static void zfcp_erp_enqueue_ptp_port(struct zfcp_adapter *adapter) { struct zfcp_port *port; @@ -778,7 +767,7 @@ static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *act) { struct zfcp_adapter *adapter = act->adapter; - if (zfcp_erp_adapter_strategy_open_qdio(act)) { + if (zfcp_qdio_open(adapter->qdio)) { atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status); diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index d99c9dc9cfcb..2511f92302dd 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -307,6 +307,7 @@ static int zfcp_qdio_allocate(struct zfcp_qdio *qdio) return -ENOMEM; zfcp_qdio_setup_init_data(&init_data, qdio); + init_waitqueue_head(&qdio->req_q_wq); return qdio_allocate(&init_data); } @@ -391,6 +392,7 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio) /* set index of first avalable SBALS / number of available SBALS */ qdio->req_q_idx = 0; atomic_set(&qdio->req_q_free, QDIO_MAX_BUFFERS_PER_Q); + atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &qdio->adapter->status); return 0; -- cgit v1.2.3-59-g8ed1b From 51780d2c38a7294c2c302ae9d2ea517bd4153dec Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Thu, 2 Dec 2010 15:16:18 +0100 Subject: [SCSI] zfcp: Add __init declaration to zfcp_cache_hw_align The function zfcp_cache_hw_align is only called from zfcp_module_init, so it should be declared with __init as well. Reviewed-by: Steffen Maier Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_aux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 352ca0d4ca25..51c666fb67a4 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -45,8 +45,8 @@ static char *init_device; module_param_named(device, init_device, charp, 0400); MODULE_PARM_DESC(device, "specify initial device"); -static struct kmem_cache *zfcp_cache_hw_align(const char *name, - unsigned long size) +static struct kmem_cache * __init zfcp_cache_hw_align(const char *name, + unsigned long size) { return kmem_cache_create(name, size, roundup_pow_of_two(size), 0, NULL); } -- cgit v1.2.3-59-g8ed1b From 0d81b4e8dcc4177726f30a1ac8df1f726d2a7c0c Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Wed, 8 Dec 2010 17:30:46 +0100 Subject: [SCSI] zfcp: Add allow_lun_scan module parameter The zfcpdump tool requires a method to attach exactly one LUN. The easiest way to achieve this is to add a new zfcp module parameter. When allow_lun_scan is set to "false", zfcp only accepts LUNs that have been configured through the unit_add sysfs interface. Reviewed-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_scsi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 59a653d15a19..ddb5800823a9 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -30,6 +30,10 @@ module_param_named(dif, enable_dif, bool, 0600); MODULE_PARM_DESC(dif, "Enable DIF/DIX data integrity support"); #endif +static bool allow_lun_scan = 1; +module_param(allow_lun_scan, bool, 0600); +MODULE_PARM_DESC(allow_lun_scan, "For NPIV, scan and attach all storage LUNs"); + static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth, int reason) { @@ -130,6 +134,7 @@ static int zfcp_scsi_slave_alloc(struct scsi_device *sdev) struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); struct zfcp_port *port; struct zfcp_unit *unit; + int npiv = adapter->connection_features & FSF_FEATURE_NPIV_MODE; port = zfcp_get_port_by_wwpn(adapter, rport->port_name); if (!port) @@ -139,7 +144,7 @@ static int zfcp_scsi_slave_alloc(struct scsi_device *sdev) if (unit) put_device(&unit->dev); - if (!unit && !(adapter->connection_features & FSF_FEATURE_NPIV_MODE)) { + if (!unit && !(allow_lun_scan && npiv)) { put_device(&port->dev); return -ENXIO; } -- cgit v1.2.3-59-g8ed1b From 058548ae23f5811d0ccdb39d5ad40f078aca63ef Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 9 Dec 2010 09:37:56 -0800 Subject: [SCSI] iscsi: add module alias Since iscsi transport can be built as a module and uses netlink socket to communicate. The module should have an alias to autoload when socket of NETLINK_ISCSI type is requested. Signed-off-by: Stephen Hemminger Acked-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_iscsi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 332387a6bc25..f905ecb5704d 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -2200,3 +2200,4 @@ MODULE_AUTHOR("Mike Christie , " MODULE_DESCRIPTION("iSCSI Transport Interface"); MODULE_LICENSE("GPL"); MODULE_VERSION(ISCSI_TRANSPORT_VERSION); +MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_ISCSI); -- cgit v1.2.3-59-g8ed1b From 402c6eec1bd04581c04de758e4efddc020b78f91 Mon Sep 17 00:00:00 2001 From: Robert Jennings Date: Thu, 9 Dec 2010 14:03:59 -0600 Subject: [SCSI] ibmvfc: Improve ibmvfc_async_desc memory layout By changing field ordering we can avoid a couple of memory holes in the tables that use the ibmvfc_async_desc structure. Signed-off-by: Robert Jennings Acked-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvfc.c | 28 ++++++++++++++-------------- drivers/scsi/ibmvscsi/ibmvfc.h | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 57cad7e20caa..b7650613b8c2 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -2493,23 +2493,23 @@ static void ibmvfc_terminate_rport_io(struct fc_rport *rport) } static const struct ibmvfc_async_desc ae_desc [] = { - { IBMVFC_AE_ELS_PLOGI, "PLOGI", IBMVFC_DEFAULT_LOG_LEVEL + 1 }, - { IBMVFC_AE_ELS_LOGO, "LOGO", IBMVFC_DEFAULT_LOG_LEVEL + 1 }, - { IBMVFC_AE_ELS_PRLO, "PRLO", IBMVFC_DEFAULT_LOG_LEVEL + 1 }, - { IBMVFC_AE_SCN_NPORT, "N-Port SCN", IBMVFC_DEFAULT_LOG_LEVEL + 1 }, - { IBMVFC_AE_SCN_GROUP, "Group SCN", IBMVFC_DEFAULT_LOG_LEVEL + 1 }, - { IBMVFC_AE_SCN_DOMAIN, "Domain SCN", IBMVFC_DEFAULT_LOG_LEVEL }, - { IBMVFC_AE_SCN_FABRIC, "Fabric SCN", IBMVFC_DEFAULT_LOG_LEVEL }, - { IBMVFC_AE_LINK_UP, "Link Up", IBMVFC_DEFAULT_LOG_LEVEL }, - { IBMVFC_AE_LINK_DOWN, "Link Down", IBMVFC_DEFAULT_LOG_LEVEL }, - { IBMVFC_AE_LINK_DEAD, "Link Dead", IBMVFC_DEFAULT_LOG_LEVEL }, - { IBMVFC_AE_HALT, "Halt", IBMVFC_DEFAULT_LOG_LEVEL }, - { IBMVFC_AE_RESUME, "Resume", IBMVFC_DEFAULT_LOG_LEVEL }, - { IBMVFC_AE_ADAPTER_FAILED, "Adapter Failed", IBMVFC_DEFAULT_LOG_LEVEL }, + { "PLOGI", IBMVFC_AE_ELS_PLOGI, IBMVFC_DEFAULT_LOG_LEVEL + 1 }, + { "LOGO", IBMVFC_AE_ELS_LOGO, IBMVFC_DEFAULT_LOG_LEVEL + 1 }, + { "PRLO", IBMVFC_AE_ELS_PRLO, IBMVFC_DEFAULT_LOG_LEVEL + 1 }, + { "N-Port SCN", IBMVFC_AE_SCN_NPORT, IBMVFC_DEFAULT_LOG_LEVEL + 1 }, + { "Group SCN", IBMVFC_AE_SCN_GROUP, IBMVFC_DEFAULT_LOG_LEVEL + 1 }, + { "Domain SCN", IBMVFC_AE_SCN_DOMAIN, IBMVFC_DEFAULT_LOG_LEVEL }, + { "Fabric SCN", IBMVFC_AE_SCN_FABRIC, IBMVFC_DEFAULT_LOG_LEVEL }, + { "Link Up", IBMVFC_AE_LINK_UP, IBMVFC_DEFAULT_LOG_LEVEL }, + { "Link Down", IBMVFC_AE_LINK_DOWN, IBMVFC_DEFAULT_LOG_LEVEL }, + { "Link Dead", IBMVFC_AE_LINK_DEAD, IBMVFC_DEFAULT_LOG_LEVEL }, + { "Halt", IBMVFC_AE_HALT, IBMVFC_DEFAULT_LOG_LEVEL }, + { "Resume", IBMVFC_AE_RESUME, IBMVFC_DEFAULT_LOG_LEVEL }, + { "Adapter Failed", IBMVFC_AE_ADAPTER_FAILED, IBMVFC_DEFAULT_LOG_LEVEL }, }; static const struct ibmvfc_async_desc unknown_ae = { - 0, "Unknown async", IBMVFC_DEFAULT_LOG_LEVEL + "Unknown async", 0, IBMVFC_DEFAULT_LOG_LEVEL }; /** diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index ef663e7c9bbc..834c37fc7ce9 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h @@ -542,8 +542,8 @@ enum ibmvfc_async_event { }; struct ibmvfc_async_desc { - enum ibmvfc_async_event ae; const char *desc; + enum ibmvfc_async_event ae; int log_level; }; -- cgit v1.2.3-59-g8ed1b From df0f1933eb5454a5c481311837076056557467ad Mon Sep 17 00:00:00 2001 From: Maggie Zhang Date: Thu, 9 Dec 2010 19:07:46 -0800 Subject: [SCSI] bfa: remove unused and empty functions Removed unused and empty functions. Signed-off-by: Maggie Zhang Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa.h | 10 -- drivers/scsi/bfa/bfa_core.c | 79 +----------- drivers/scsi/bfa/bfa_fcpim.c | 82 +----------- drivers/scsi/bfa/bfa_fcpim.h | 4 - drivers/scsi/bfa/bfa_fcs.c | 20 --- drivers/scsi/bfa/bfa_fcs.h | 20 --- drivers/scsi/bfa/bfa_fcs_lport.c | 49 -------- drivers/scsi/bfa/bfa_fcs_rport.c | 116 ----------------- drivers/scsi/bfa/bfa_ioc.c | 23 +--- drivers/scsi/bfa/bfa_ioc.h | 1 - drivers/scsi/bfa/bfa_plog.h | 3 - drivers/scsi/bfa/bfa_port.c | 14 --- drivers/scsi/bfa/bfa_port.h | 1 - drivers/scsi/bfa/bfa_svc.c | 260 --------------------------------------- drivers/scsi/bfa/bfa_svc.h | 32 ----- 15 files changed, 4 insertions(+), 710 deletions(-) diff --git a/drivers/scsi/bfa/bfa.h b/drivers/scsi/bfa/bfa.h index ff2bd07161f7..7ed13ce6d6aa 100644 --- a/drivers/scsi/bfa/bfa.h +++ b/drivers/scsi/bfa/bfa.h @@ -33,7 +33,6 @@ typedef void (*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete); * Interrupt message handlers */ void bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m); -void bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func); /* * Request and response queue related defines @@ -397,8 +396,6 @@ void bfa_cb_init(void *bfad, bfa_status_t status); void bfa_cb_updateq(void *bfad, bfa_status_t status); bfa_boolean_t bfa_intx(struct bfa_s *bfa); -void bfa_intx_disable(struct bfa_s *bfa); -void bfa_intx_enable(struct bfa_s *bfa); void bfa_isr_enable(struct bfa_s *bfa); void bfa_isr_disable(struct bfa_s *bfa); @@ -410,16 +407,12 @@ typedef void (*bfa_cb_ioc_t) (void *cbarg, enum bfa_status status); void bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr); void bfa_get_attr(struct bfa_s *bfa, struct bfa_ioc_attr_s *ioc_attr); -void bfa_adapter_get_attr(struct bfa_s *bfa, - struct bfa_adapter_attr_s *ad_attr); -u64 bfa_adapter_get_id(struct bfa_s *bfa); bfa_status_t bfa_iocfc_israttr_set(struct bfa_s *bfa, struct bfa_iocfc_intr_attr_s *attr); void bfa_iocfc_enable(struct bfa_s *bfa); void bfa_iocfc_disable(struct bfa_s *bfa); -void bfa_chip_reset(struct bfa_s *bfa); void bfa_timer_tick(struct bfa_s *bfa); #define bfa_timer_start(_bfa, _timer, _timercb, _arg, _timeout) \ bfa_timer_begin(&(_bfa)->timer_mod, _timer, _timercb, _arg, _timeout) @@ -431,8 +424,5 @@ bfa_status_t bfa_debug_fwtrc(struct bfa_s *bfa, void *trcdata, int *trclen); bfa_status_t bfa_debug_fwsave(struct bfa_s *bfa, void *trcdata, int *trclen); bfa_status_t bfa_debug_fwcore(struct bfa_s *bfa, void *buf, u32 *offset, int *buflen); -void bfa_debug_fwsave_clear(struct bfa_s *bfa); -bfa_status_t bfa_fw_stats_get(struct bfa_s *bfa, void *data); -bfa_status_t bfa_fw_stats_clear(struct bfa_s *bfa); #endif /* __BFA_H__ */ diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c index 2345f48dc57f..90e0f81ae425 100644 --- a/drivers/scsi/bfa/bfa_core.c +++ b/drivers/scsi/bfa/bfa_core.c @@ -104,9 +104,6 @@ bfa_msix_all(struct bfa_s *bfa, int vec) bfa_intx(bfa); } -/* - * hal_intr_api - */ bfa_boolean_t bfa_intx(struct bfa_s *bfa) { @@ -150,18 +147,6 @@ bfa_intx(struct bfa_s *bfa) return BFA_TRUE; } -void -bfa_intx_enable(struct bfa_s *bfa) -{ - writel(bfa->iocfc.intr_mask, bfa->iocfc.bfa_regs.intr_mask); -} - -void -bfa_intx_disable(struct bfa_s *bfa) -{ - writel(-1L, bfa->iocfc.bfa_regs.intr_mask); -} - void bfa_isr_enable(struct bfa_s *bfa) { @@ -317,18 +302,12 @@ bfa_msix_lpu_err(struct bfa_s *bfa, int vec) } } -void -bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func) -{ - bfa_isrs[mc] = isr_func; -} - /* * BFA IOC FC related functions */ /* - * hal_ioc_pvt BFA IOC private functions + * BFA IOC private functions */ static void @@ -735,9 +714,6 @@ bfa_iocfc_reset_cbfn(void *bfa_arg) bfa_isr_enable(bfa); } -/* - * hal_ioc_public - */ /* * Query IOC memory requirement information. @@ -856,18 +832,6 @@ bfa_iocfc_isr(void *bfaarg, struct bfi_mbmsg_s *m) } } -void -bfa_adapter_get_attr(struct bfa_s *bfa, struct bfa_adapter_attr_s *ad_attr) -{ - bfa_ioc_get_adapter_attr(&bfa->ioc, ad_attr); -} - -u64 -bfa_adapter_get_id(struct bfa_s *bfa) -{ - return bfa_ioc_get_adid(&bfa->ioc); -} - void bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr) { @@ -998,9 +962,6 @@ bfa_iocfc_get_pbc_vports(struct bfa_s *bfa, struct bfi_pbc_vport_s *pbc_vport) return cfgrsp->pbc_cfg.nvports; } -/* - * hal_api - */ /* * Use this function query the memory requirement of the BFA library. @@ -1337,15 +1298,6 @@ bfa_debug_fwsave(struct bfa_s *bfa, void *trcdata, int *trclen) return bfa_ioc_debug_fwsave(&bfa->ioc, trcdata, trclen); } -/* - * Clear the saved firmware trace information of an IOC. - */ -void -bfa_debug_fwsave_clear(struct bfa_s *bfa) -{ - bfa_ioc_debug_fwsave_clear(&bfa->ioc); -} - /* * Fetch firmware trace data. * @@ -1378,32 +1330,3 @@ bfa_debug_fwcore(struct bfa_s *bfa, void *buf, u32 *offset, int *buflen) { return bfa_ioc_debug_fwcore(&bfa->ioc, buf, offset, buflen); } -/* - * Reset hw semaphore & usage cnt regs and initialize. - */ -void -bfa_chip_reset(struct bfa_s *bfa) -{ - bfa_ioc_ownership_reset(&bfa->ioc); - bfa_ioc_pll_init(&bfa->ioc); -} - -/* - * Fetch firmware statistics data. - * - * @param[in] bfa BFA instance - * @param[out] data Firmware stats buffer - * - * @retval BFA_STATUS_OK Firmware trace is fetched. - */ -bfa_status_t -bfa_fw_stats_get(struct bfa_s *bfa, void *data) -{ - return bfa_ioc_fw_stats_get(&bfa->ioc, data); -} - -bfa_status_t -bfa_fw_stats_clear(struct bfa_s *bfa) -{ - return bfa_ioc_fw_stats_clear(&bfa->ioc); -} diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c index 135c4427801c..0e7f3807dba2 100644 --- a/drivers/scsi/bfa/bfa_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcpim.c @@ -107,9 +107,6 @@ enum bfa_itnim_event { if ((__fcpim)->profile_start) \ (__fcpim)->profile_start(__ioim); \ } while (0) -/* - * hal_ioim_sm - */ /* * IO state machine events @@ -295,7 +292,7 @@ static void bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim, enum bfa_tskim_event event); /* - * hal_fcpim_mod BFA FCP Initiator Mode module + * BFA FCP Initiator Mode module */ /* @@ -357,10 +354,6 @@ bfa_fcpim_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, static void bfa_fcpim_detach(struct bfa_s *bfa) { - struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); - - bfa_ioim_detach(fcpim); - bfa_tskim_detach(fcpim); } static void @@ -1586,13 +1579,6 @@ bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim, return BFA_STATUS_OK; } -void -bfa_itnim_get_stats(struct bfa_itnim_s *itnim, - struct bfa_itnim_iostats_s *stats) -{ - *stats = itnim->stats; -} - void bfa_itnim_clear_stats(struct bfa_itnim_s *itnim) { @@ -2213,11 +2199,6 @@ bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) } - -/* - * hal_ioim_private - */ - static void __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete) { @@ -2421,25 +2402,6 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim) (bfa_cb_ioim_get_size(ioim->dio) & (sizeof(u32) - 1))) bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa)); -#ifdef IOIM_ADVANCED - m->cmnd.crn = bfa_cb_ioim_get_crn(ioim->dio); - m->cmnd.priority = bfa_cb_ioim_get_priority(ioim->dio); - m->cmnd.taskattr = bfa_cb_ioim_get_taskattr(ioim->dio); - - /* - * Handle large CDB (>16 bytes). - */ - m->cmnd.addl_cdb_len = (bfa_cb_ioim_get_cdblen(ioim->dio) - - FCP_CMND_CDB_LEN) / sizeof(u32); - if (m->cmnd.addl_cdb_len) { - memcpy(&m->cmnd.cdb + 1, (scsi_cdb_t *) - bfa_cb_ioim_get_cdb(ioim->dio) + 1, - m->cmnd.addl_cdb_len * sizeof(u32)); - fcp_cmnd_fcpdl(&m->cmnd) = - cpu_to_be32(bfa_cb_ioim_get_size(ioim->dio)); - } -#endif - /* * queue I/O message to firmware */ @@ -2653,11 +2615,6 @@ bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim, bfa_boolean_t iotov) } - -/* - * hal_ioim_friend - */ - /* * Memory allocation and initialization. */ @@ -2722,14 +2679,6 @@ bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo) } } -/* - * Driver detach time call. - */ -void -bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim) -{ -} - void bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m) { @@ -2903,11 +2852,6 @@ bfa_ioim_tov(struct bfa_ioim_s *ioim) } - -/* - * hal_ioim_api - */ - /* * Allocate IOIM resource for initiator mode I/O request. */ @@ -3234,11 +3178,6 @@ bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim, enum bfa_tskim_event event) } - -/* - * hal_tskim_private - */ - static void __bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete) { @@ -3452,11 +3391,6 @@ bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim) } - -/* - * hal_tskim_friend - */ - /* * Notification on completions from related ioim. */ @@ -3521,14 +3455,6 @@ bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo) bfa_meminfo_kva(minfo) = (u8 *) tskim; } -void -bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim) -{ - /* - * @todo - */ -} - void bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m) { @@ -3556,12 +3482,6 @@ bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m) } - -/* - * hal_tskim_api - */ - - struct bfa_tskim_s * bfa_tskim_alloc(struct bfa_s *bfa, struct bfad_tskim_s *dtsk) { diff --git a/drivers/scsi/bfa/bfa_fcpim.h b/drivers/scsi/bfa/bfa_fcpim.h index db53717eeb4b..18bdc44432ac 100644 --- a/drivers/scsi/bfa/bfa_fcpim.h +++ b/drivers/scsi/bfa/bfa_fcpim.h @@ -220,7 +220,6 @@ bfa_ioim_get_iotag(struct bfa_ioim_s *ioim) */ void bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo); -void bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim); void bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg); void bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg); @@ -232,7 +231,6 @@ void bfa_ioim_tov(struct bfa_ioim_s *ioim); void bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo); -void bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim); void bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg); void bfa_tskim_iodone(struct bfa_tskim_s *tskim); void bfa_tskim_iocdisable(struct bfa_tskim_s *tskim); @@ -296,8 +294,6 @@ void bfa_itnim_delete(struct bfa_itnim_s *itnim); void bfa_itnim_online(struct bfa_itnim_s *itnim, bfa_boolean_t seq_rec); void bfa_itnim_offline(struct bfa_itnim_s *itnim); -void bfa_itnim_get_stats(struct bfa_itnim_s *itnim, - struct bfa_itnim_iostats_s *stats); void bfa_itnim_clear_stats(struct bfa_itnim_s *itnim); bfa_status_t bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim, struct bfa_itnim_ioprofile_s *ioprofile); diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c index 045d7e87b632..5b561bde2264 100644 --- a/drivers/scsi/bfa/bfa_fcs.c +++ b/drivers/scsi/bfa/bfa_fcs.c @@ -1038,14 +1038,6 @@ bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs) bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_START); } -/* - * Suspend fabric activity as part of driver suspend. - */ -void -bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs) -{ -} - bfa_boolean_t bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric) { @@ -1146,18 +1138,6 @@ bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric) return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_online); } -/* - * brief - * - */ -bfa_status_t -bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf, struct bfa_fcs_s *fcs, - struct bfa_lport_cfg_s *port_cfg, struct bfad_vf_s *vf_drv) -{ - bfa_sm_set_state(vf, bfa_fcs_fabric_sm_uninit); - return BFA_STATUS_OK; -} - /* * Lookup for a vport withing a fabric given its pwwn */ diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h index 5a8b928f8db3..fcb54e5ef331 100644 --- a/drivers/scsi/bfa/bfa_fcs.h +++ b/drivers/scsi/bfa/bfa_fcs.h @@ -316,8 +316,6 @@ void bfa_fcs_lport_add_rport(struct bfa_fcs_lport_s *port, struct bfa_fcs_rport_s *rport); void bfa_fcs_lport_del_rport(struct bfa_fcs_lport_s *port, struct bfa_fcs_rport_s *rport); -void bfa_fcs_lport_modinit(struct bfa_fcs_s *fcs); -void bfa_fcs_lport_modexit(struct bfa_fcs_s *fcs); void bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *vport); void bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *vport); void bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *vport); @@ -359,9 +357,6 @@ bfa_status_t bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport); bfa_status_t bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport); void bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport, struct bfa_vport_attr_s *vport_attr); -void bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport, - struct bfa_vport_stats_s *vport_stats); -void bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport); struct bfa_fcs_vport_s *bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn); void bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport); @@ -437,23 +432,12 @@ bfa_fcs_rport_get_halrport(struct bfa_fcs_rport_s *rport) /* * bfa fcs rport API functions */ -bfa_status_t bfa_fcs_rport_add(struct bfa_fcs_lport_s *port, wwn_t *pwwn, - struct bfa_fcs_rport_s *rport, - struct bfad_rport_s *rport_drv); -bfa_status_t bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport); -void bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport, - struct bfa_rport_attr_s *attr); -void bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport, - struct bfa_rport_stats_s *stats); -void bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport); struct bfa_fcs_rport_s *bfa_fcs_rport_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn); struct bfa_fcs_rport_s *bfa_fcs_rport_lookup_by_nwwn( struct bfa_fcs_lport_s *port, wwn_t rnwwn); void bfa_fcs_rport_set_del_timeout(u8 rport_tmo); -void bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport, - enum bfa_port_speed speed); void bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs, u16 len); void bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport); @@ -689,7 +673,6 @@ u16 bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric); void bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs); void bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs); void bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs); -void bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs); void bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric); void bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric); void bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric, @@ -707,9 +690,6 @@ bfa_boolean_t bfa_fcs_fabric_is_auth_failed(struct bfa_fcs_fabric_s *fabric); enum bfa_port_type bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric); void bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric); void bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric); -bfa_status_t bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf, - struct bfa_fcs_s *fcs, struct bfa_lport_cfg_s *port_cfg, - struct bfad_vf_s *vf_drv); void bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric, wwn_t fabric_name); u16 bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric); diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c index 93c3588c715f..bd0c093fca66 100644 --- a/drivers/scsi/bfa/bfa_fcs_lport.c +++ b/drivers/scsi/bfa/bfa_fcs_lport.c @@ -589,28 +589,6 @@ bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port) } - -/* - * fcs_lport_api BFA FCS port API - */ -/* - * Module initialization - */ -void -bfa_fcs_lport_modinit(struct bfa_fcs_s *fcs) -{ - -} - -/* - * Module cleanup - */ -void -bfa_fcs_lport_modexit(struct bfa_fcs_s *fcs) -{ - bfa_fcs_modexit_comp(fcs); -} - /* * Unsolicited frame receive handling. */ @@ -5620,33 +5598,6 @@ bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport, attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm); } -/* - * Use this function to get vport's statistics. - * - * param[in] vport pointer to bfa_fcs_vport_t. - * param[out] stats pointer to return vport statistics in - * - * return None - */ -void -bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport, - struct bfa_vport_stats_s *stats) -{ - *stats = vport->vport_stats; -} - -/* - * Use this function to clear vport's statistics. - * - * param[in] vport pointer to bfa_fcs_vport_t. - * - * return None - */ -void -bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport) -{ - memset(&vport->vport_stats, 0, sizeof(struct bfa_vport_stats_s)); -} /* * Lookup a virtual port. Excludes base port from lookup. diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c index f5b5cbba3f43..7928bc8c1ed7 100644 --- a/drivers/scsi/bfa/bfa_fcs_rport.c +++ b/drivers/scsi/bfa/bfa_fcs_rport.c @@ -2613,106 +2613,6 @@ bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, __be16 ox_id) * fcs_rport_api FCS rport API. */ -/* - * Direct API to add a target by port wwn. This interface is used, for - * example, by bios when target pwwn is known from boot lun configuration. - */ -bfa_status_t -bfa_fcs_rport_add(struct bfa_fcs_lport_s *port, wwn_t *pwwn, - struct bfa_fcs_rport_s *rport, struct bfad_rport_s *rport_drv) -{ - bfa_trc(port->fcs, *pwwn); - - return BFA_STATUS_OK; -} - -/* - * Direct API to remove a target and its associated resources. This - * interface is used, for example, by driver to remove target - * ports from the target list for a VM. - */ -bfa_status_t -bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport_in) -{ - - struct bfa_fcs_rport_s *rport; - - bfa_trc(rport_in->fcs, rport_in->pwwn); - - rport = bfa_fcs_lport_get_rport_by_pwwn(rport_in->port, rport_in->pwwn); - if (rport == NULL) { - /* - * TBD Error handling - */ - bfa_trc(rport_in->fcs, rport_in->pid); - return BFA_STATUS_UNKNOWN_RWWN; - } - - /* - * TBD if this remote port is online, send a logo - */ - return BFA_STATUS_OK; - -} - -/* - * Remote device status for display/debug. - */ -void -bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport, - struct bfa_rport_attr_s *rport_attr) -{ - struct bfa_rport_qos_attr_s qos_attr; - bfa_fcs_lport_t *port = rport->port; - bfa_port_speed_t rport_speed = rport->rpf.rpsc_speed; - - memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s)); - - rport_attr->pid = rport->pid; - rport_attr->pwwn = rport->pwwn; - rport_attr->nwwn = rport->nwwn; - rport_attr->cos_supported = rport->fc_cos; - rport_attr->df_sz = rport->maxfrsize; - rport_attr->state = bfa_fcs_rport_get_state(rport); - rport_attr->fc_cos = rport->fc_cos; - rport_attr->cisc = rport->cisc; - rport_attr->scsi_function = rport->scsi_function; - rport_attr->curr_speed = rport->rpf.rpsc_speed; - rport_attr->assigned_speed = rport->rpf.assigned_speed; - - bfa_rport_get_qos_attr(rport->bfa_rport, &qos_attr); - rport_attr->qos_attr = qos_attr; - - rport_attr->trl_enforced = BFA_FALSE; - if (bfa_fcport_is_ratelim(port->fcs->bfa)) { - if (rport_speed == BFA_PORT_SPEED_UNKNOWN) { - /* Use default ratelim speed setting */ - rport_speed = - bfa_fcport_get_ratelim_speed(rport->fcs->bfa); - } - - if (rport_speed < bfa_fcs_lport_get_rport_max_speed(port)) - rport_attr->trl_enforced = BFA_TRUE; - } -} - -/* - * Per remote device statistics. - */ -void -bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport, - struct bfa_rport_stats_s *stats) -{ - *stats = rport->stats; -} - -void -bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport) -{ - memset((char *)&rport->stats, 0, - sizeof(struct bfa_rport_stats_s)); -} - struct bfa_fcs_rport_s * bfa_fcs_rport_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn) { @@ -2743,22 +2643,6 @@ bfa_fcs_rport_lookup_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t rnwwn) return rport; } -/* - * This API is to set the Rport's speed. Should be used when RPSC is not - * supported by the rport. - */ -void -bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport, bfa_port_speed_t speed) -{ - rport->rpf.assigned_speed = speed; - - /* Set this speed in f/w only if the RPSC speed is not available */ - if (rport->rpf.rpsc_speed == BFA_PORT_SPEED_UNKNOWN) - bfa_rport_speed(rport->bfa_rport, speed); -} - - - /* * Remote port features (RPF) implementation. */ diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index 9e82eea9b2b0..3f41d290142d 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -101,9 +101,6 @@ static void bfa_ioc_pf_disabled(struct bfa_ioc_s *ioc); static void bfa_ioc_pf_failed(struct bfa_ioc_s *ioc); static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc); -/* - * hal_ioc_sm - */ /* * IOC state machine definitions/declarations @@ -1101,7 +1098,7 @@ bfa_iocpf_sm_fail(struct bfa_iocpf_s *iocpf, enum iocpf_event event) /* - * hal_ioc_pvt BFA IOC private functions + * BFA IOC private functions */ static void @@ -1819,11 +1816,6 @@ bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc) } - -/* - * hal_ioc_public - */ - bfa_status_t bfa_ioc_pll_init(struct bfa_ioc_s *ioc) { @@ -2456,9 +2448,6 @@ bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr) bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev); } -/* - * hal_wwn_public - */ wwn_t bfa_ioc_get_pwwn(struct bfa_ioc_s *ioc) { @@ -2542,14 +2531,6 @@ bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata, int *trclen) return BFA_STATUS_OK; } -/* - * Clear saved firmware trace - */ -void -bfa_ioc_debug_fwsave_clear(struct bfa_ioc_s *ioc) -{ - ioc->dbg_fwsave_once = BFA_TRUE; -} /* * Retrieve saved firmware trace from a prior IOC failure. @@ -2735,7 +2716,7 @@ bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc) } /* - * hal_iocpf_pvt BFA IOC PF private functions + * BFA IOC PF private functions */ static void diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index f8ac05081aa3..ff012f7f0757 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h @@ -357,7 +357,6 @@ int bfa_ioc_debug_trcsz(bfa_boolean_t auto_recover); void bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave); bfa_status_t bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata, int *trclen); -void bfa_ioc_debug_fwsave_clear(struct bfa_ioc_s *ioc); bfa_status_t bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata, int *trclen); bfa_status_t bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf, diff --git a/drivers/scsi/bfa/bfa_plog.h b/drivers/scsi/bfa/bfa_plog.h index 501f0ed35cf0..bdcd8ecd4f4a 100644 --- a/drivers/scsi/bfa/bfa_plog.h +++ b/drivers/scsi/bfa/bfa_plog.h @@ -151,9 +151,6 @@ void bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid, void bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid, enum bfa_plog_eid event, u16 misc, struct fchs_s *fchdr, u32 pld_w0); -void bfa_plog_clear(struct bfa_plog_s *plog); -void bfa_plog_enable(struct bfa_plog_s *plog); -void bfa_plog_disable(struct bfa_plog_s *plog); bfa_boolean_t bfa_plog_get_setting(struct bfa_plog_s *plog); #endif /* __BFA_PORTLOG_H__ */ diff --git a/drivers/scsi/bfa/bfa_port.c b/drivers/scsi/bfa/bfa_port.c index 35277cb9a9e5..fa57b128b3d8 100644 --- a/drivers/scsi/bfa/bfa_port.c +++ b/drivers/scsi/bfa/bfa_port.c @@ -457,17 +457,3 @@ bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc, bfa_trc(port, 0); } - -/* - * bfa_port_detach() - * - * - * @param[in] port - Pointer to the Port module data structure - * - * @return void - */ -void -bfa_port_detach(struct bfa_port_s *port) -{ - bfa_trc(port, 0); -} diff --git a/drivers/scsi/bfa/bfa_port.h b/drivers/scsi/bfa/bfa_port.h index dbce9dfd056b..c4ee9db6b470 100644 --- a/drivers/scsi/bfa/bfa_port.h +++ b/drivers/scsi/bfa/bfa_port.h @@ -48,7 +48,6 @@ struct bfa_port_s { void bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc, void *dev, struct bfa_trc_mod_s *trcmod); -void bfa_port_detach(struct bfa_port_s *port); void bfa_port_hbfail(void *arg); bfa_status_t bfa_port_get_stats(struct bfa_port_s *port, diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c index 04b3349ad3a1..3a2bee4d42dd 100644 --- a/drivers/scsi/bfa/bfa_svc.c +++ b/drivers/scsi/bfa/bfa_svc.c @@ -437,23 +437,6 @@ bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid, } } -void -bfa_plog_clear(struct bfa_plog_s *plog) -{ - plog->head = plog->tail = 0; -} - -void -bfa_plog_enable(struct bfa_plog_s *plog) -{ - plog->plog_enabled = 1; -} - -void -bfa_plog_disable(struct bfa_plog_s *plog) -{ - plog->plog_enabled = 0; -} bfa_boolean_t bfa_plog_get_setting(struct bfa_plog_s *plog) @@ -1853,14 +1836,6 @@ bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn, bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN); } -/* - * Initiate a lport logout (flogi). - */ -void -bfa_lps_flogo(struct bfa_lps_s *lps) -{ - bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT); -} /* * Initiate a lport FDSIC logout. @@ -3818,89 +3793,6 @@ bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg) return BFA_STATUS_OK; } -/* - * Fetch FCQoS port statistics - */ -bfa_status_t -bfa_fcport_get_qos_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats, - bfa_cb_port_t cbfn, void *cbarg) -{ - /* Meaningful only for FC mode */ - bfa_assert(bfa_ioc_get_fcmode(&bfa->ioc)); - - return bfa_fcport_get_stats(bfa, stats, cbfn, cbarg); -} - -/* - * Reset FCoE port statistics - */ -bfa_status_t -bfa_fcport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg) -{ - /* Meaningful only for FC mode */ - bfa_assert(bfa_ioc_get_fcmode(&bfa->ioc)); - - return bfa_fcport_clear_stats(bfa, cbfn, cbarg); -} - -/* - * Fetch FCQoS port statistics - */ -bfa_status_t -bfa_fcport_get_fcoe_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats, - bfa_cb_port_t cbfn, void *cbarg) -{ - /* Meaningful only for FCoE mode */ - bfa_assert(!bfa_ioc_get_fcmode(&bfa->ioc)); - - return bfa_fcport_get_stats(bfa, stats, cbfn, cbarg); -} - -/* - * Reset FCoE port statistics - */ -bfa_status_t -bfa_fcport_clear_fcoe_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg) -{ - /* Meaningful only for FCoE mode */ - bfa_assert(!bfa_ioc_get_fcmode(&bfa->ioc)); - - return bfa_fcport_clear_stats(bfa, cbfn, cbarg); -} - -void -bfa_fcport_qos_get_attr(struct bfa_s *bfa, struct bfa_qos_attr_s *qos_attr) -{ - struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); - - qos_attr->state = fcport->qos_attr.state; - qos_attr->total_bb_cr = be32_to_cpu(fcport->qos_attr.total_bb_cr); -} - -void -bfa_fcport_qos_get_vc_attr(struct bfa_s *bfa, - struct bfa_qos_vc_attr_s *qos_vc_attr) -{ - struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); - struct bfa_qos_vc_attr_s *bfa_vc_attr = &fcport->qos_vc_attr; - u32 i = 0; - - qos_vc_attr->total_vc_count = be16_to_cpu(bfa_vc_attr->total_vc_count); - qos_vc_attr->shared_credit = be16_to_cpu(bfa_vc_attr->shared_credit); - qos_vc_attr->elp_opmode_flags = - be32_to_cpu(bfa_vc_attr->elp_opmode_flags); - - /* Individual VC info */ - while (i < qos_vc_attr->total_vc_count) { - qos_vc_attr->vc_info[i].vc_credit = - bfa_vc_attr->vc_info[i].vc_credit; - qos_vc_attr->vc_info[i].borrow_credit = - bfa_vc_attr->vc_info[i].borrow_credit; - qos_vc_attr->vc_info[i].priority = - bfa_vc_attr->vc_info[i].priority; - ++i; - } -} /* * Fetch port attributes. @@ -3924,59 +3816,6 @@ bfa_fcport_is_ratelim(struct bfa_s *bfa) } -void -bfa_fcport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off) -{ - struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); - enum bfa_ioc_type_e ioc_type = bfa_get_type(bfa); - - bfa_trc(bfa, on_off); - bfa_trc(bfa, fcport->cfg.qos_enabled); - - bfa_trc(bfa, ioc_type); - - if (ioc_type == BFA_IOC_TYPE_FC) { - fcport->cfg.qos_enabled = on_off; - /* - * Notify fcpim of the change in QoS state - */ - bfa_fcpim_update_ioredirect(bfa); - } -} - -void -bfa_fcport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off) -{ - struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); - - bfa_trc(bfa, on_off); - bfa_trc(bfa, fcport->cfg.ratelimit); - - fcport->cfg.ratelimit = on_off; - if (fcport->cfg.trl_def_speed == BFA_PORT_SPEED_UNKNOWN) - fcport->cfg.trl_def_speed = BFA_PORT_SPEED_1GBPS; -} - -/* - * Configure default minimum ratelim speed - */ -bfa_status_t -bfa_fcport_cfg_ratelim_speed(struct bfa_s *bfa, enum bfa_port_speed speed) -{ - struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); - - bfa_trc(bfa, speed); - - /* Auto and speeds greater than the supported speed, are invalid */ - if ((speed == BFA_PORT_SPEED_AUTO) || (speed > fcport->speed_sup)) { - bfa_trc(bfa, fcport->speed_sup); - return BFA_STATUS_UNSUPP_SPEED; - } - - fcport->cfg.trl_def_speed = speed; - - return BFA_STATUS_OK; -} /* * Get default minimum ratelim speed @@ -3990,32 +3829,6 @@ bfa_fcport_get_ratelim_speed(struct bfa_s *bfa) return fcport->cfg.trl_def_speed; } -void -bfa_fcport_busy(struct bfa_s *bfa, bfa_boolean_t status) -{ - struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); - - bfa_trc(bfa, status); - bfa_trc(bfa, fcport->diag_busy); - - fcport->diag_busy = status; -} - -void -bfa_fcport_beacon(void *dev, bfa_boolean_t beacon, - bfa_boolean_t link_e2e_beacon) -{ - struct bfa_s *bfa = dev; - struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); - - bfa_trc(bfa, beacon); - bfa_trc(bfa, link_e2e_beacon); - bfa_trc(bfa, fcport->beacon); - bfa_trc(bfa, fcport->link_e2e_beacon); - - fcport->beacon = beacon; - fcport->link_e2e_beacon = link_e2e_beacon; -} bfa_boolean_t bfa_fcport_is_linkup(struct bfa_s *bfa) @@ -4036,63 +3849,6 @@ bfa_fcport_is_qos_enabled(struct bfa_s *bfa) return fcport->cfg.qos_enabled; } -bfa_status_t -bfa_trunk_get_attr(struct bfa_s *bfa, struct bfa_trunk_attr_s *attr) - -{ - struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); - struct bfa_fcport_trunk_s *trunk = &fcport->trunk; - - bfa_trc(bfa, fcport->cfg.trunked); - bfa_trc(bfa, trunk->attr.state); - *attr = trunk->attr; - attr->port_id = bfa_lps_get_base_pid(bfa); - - return BFA_STATUS_OK; -} - -void -bfa_trunk_enable_cfg(struct bfa_s *bfa) -{ - struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); - struct bfa_fcport_trunk_s *trunk = &fcport->trunk; - - bfa_trc(bfa, 1); - trunk->attr.state = BFA_TRUNK_OFFLINE; - fcport->cfg.trunked = BFA_TRUE; -} - -bfa_status_t -bfa_trunk_enable(struct bfa_s *bfa) -{ - struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); - struct bfa_fcport_trunk_s *trunk = &fcport->trunk; - - bfa_trc(bfa, 1); - - trunk->attr.state = BFA_TRUNK_OFFLINE; - bfa_fcport_disable(bfa); - fcport->cfg.trunked = BFA_TRUE; - bfa_fcport_enable(bfa); - - return BFA_STATUS_OK; -} - -bfa_status_t -bfa_trunk_disable(struct bfa_s *bfa) -{ - struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); - struct bfa_fcport_trunk_s *trunk = &fcport->trunk; - - bfa_trc(bfa, 0); - trunk->attr.state = BFA_TRUNK_DISABLED; - bfa_fcport_disable(bfa); - fcport->cfg.trunked = BFA_FALSE; - bfa_fcport_enable(bfa); - return BFA_STATUS_OK; -} - - /* * Rport State machine functions */ @@ -4876,22 +4632,6 @@ bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed) bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED); } -void -bfa_rport_get_stats(struct bfa_rport_s *rport, - struct bfa_rport_hal_stats_s *stats) -{ - *stats = rport->stats; -} - -void -bfa_rport_get_qos_attr(struct bfa_rport_s *rport, - struct bfa_rport_qos_attr_s *qos_attr) -{ - qos_attr->qos_priority = rport->qos_attr.qos_priority; - qos_attr->qos_flow_id = be32_to_cpu(rport->qos_attr.qos_flow_id); - -} - void bfa_rport_clear_stats(struct bfa_rport_s *rport) { diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h index e2349d5cdb93..0e23c1bfcba0 100644 --- a/drivers/scsi/bfa/bfa_svc.h +++ b/drivers/scsi/bfa/bfa_svc.h @@ -500,30 +500,9 @@ void bfa_fcport_event_register(struct bfa_s *bfa, void (*event_cbfn) (void *cbarg, enum bfa_port_linkstate event), void *event_cbarg); bfa_boolean_t bfa_fcport_is_disabled(struct bfa_s *bfa); -void bfa_fcport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off); -void bfa_fcport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off); -bfa_status_t bfa_fcport_cfg_ratelim_speed(struct bfa_s *bfa, - enum bfa_port_speed speed); enum bfa_port_speed bfa_fcport_get_ratelim_speed(struct bfa_s *bfa); void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit); -void bfa_fcport_busy(struct bfa_s *bfa, bfa_boolean_t status); -void bfa_fcport_beacon(void *dev, bfa_boolean_t beacon, - bfa_boolean_t link_e2e_beacon); -void bfa_fcport_qos_get_attr(struct bfa_s *bfa, - struct bfa_qos_attr_s *qos_attr); -void bfa_fcport_qos_get_vc_attr(struct bfa_s *bfa, - struct bfa_qos_vc_attr_s *qos_vc_attr); -bfa_status_t bfa_fcport_get_qos_stats(struct bfa_s *bfa, - union bfa_fcport_stats_u *stats, - bfa_cb_port_t cbfn, void *cbarg); -bfa_status_t bfa_fcport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, - void *cbarg); -bfa_status_t bfa_fcport_get_fcoe_stats(struct bfa_s *bfa, - union bfa_fcport_stats_u *stats, - bfa_cb_port_t cbfn, void *cbarg); -bfa_status_t bfa_fcport_clear_fcoe_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, - void *cbarg); bfa_boolean_t bfa_fcport_is_ratelim(struct bfa_s *bfa); bfa_boolean_t bfa_fcport_is_linkup(struct bfa_s *bfa); bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa, @@ -542,8 +521,6 @@ void bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info); void bfa_rport_offline(struct bfa_rport_s *rport); void bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed); -void bfa_rport_get_stats(struct bfa_rport_s *rport, - struct bfa_rport_hal_stats_s *stats); void bfa_rport_clear_stats(struct bfa_rport_s *rport); void bfa_cb_rport_online(void *rport); void bfa_cb_rport_offline(void *rport); @@ -553,8 +530,6 @@ void bfa_cb_rport_qos_scn_flowid(void *rport, void bfa_cb_rport_qos_scn_prio(void *rport, struct bfa_rport_qos_attr_s old_qos_attr, struct bfa_rport_qos_attr_s new_qos_attr); -void bfa_rport_get_qos_attr(struct bfa_rport_s *rport, - struct bfa_rport_qos_attr_s *qos_attr); /* * bfa fcxp API functions @@ -625,7 +600,6 @@ void bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, bfa_boolean_t auth_en); void bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn, wwn_t nwwn); -void bfa_lps_flogo(struct bfa_lps_s *lps); void bfa_lps_fdisclogo(struct bfa_lps_s *lps); u8 bfa_lps_get_tag(struct bfa_lps_s *lps); bfa_boolean_t bfa_lps_is_npiv_en(struct bfa_lps_s *lps); @@ -647,10 +621,4 @@ void bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status); void bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg); void bfa_cb_lps_cvl_event(void *bfad, void *uarg); -void bfa_trunk_enable_cfg(struct bfa_s *bfa); -bfa_status_t bfa_trunk_enable(struct bfa_s *bfa); -bfa_status_t bfa_trunk_disable(struct bfa_s *bfa); -bfa_status_t bfa_trunk_get_attr(struct bfa_s *bfa, - struct bfa_trunk_attr_s *attr); - #endif /* __BFA_SVC_H__ */ -- cgit v1.2.3-59-g8ed1b From f7f73812e95077c19a2801bbf4f483fcdab5232f Mon Sep 17 00:00:00 2001 From: Maggie Zhang Date: Thu, 9 Dec 2010 19:08:43 -0800 Subject: [SCSI] bfa: clean up one line functions Cleaned up one line functions. Signed-off-by: Maggie Zhang Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa.h | 17 --- drivers/scsi/bfa/bfa_core.c | 173 ++---------------------- drivers/scsi/bfa/bfa_fcpim.c | 2 +- drivers/scsi/bfa/bfa_fcs.c | 172 ++++-------------------- drivers/scsi/bfa/bfa_fcs.h | 87 +++++++++--- drivers/scsi/bfa/bfa_fcs_fcpim.c | 18 +-- drivers/scsi/bfa/bfa_fcs_lport.c | 65 ++++----- drivers/scsi/bfa/bfa_fcs_rport.c | 97 ++------------ drivers/scsi/bfa/bfa_ioc.c | 280 +++++++-------------------------------- drivers/scsi/bfa/bfa_ioc.h | 19 +-- drivers/scsi/bfa/bfa_ioc_cb.c | 2 +- drivers/scsi/bfa/bfa_ioc_ct.c | 12 +- drivers/scsi/bfa/bfa_plog.h | 1 - drivers/scsi/bfa/bfa_port.c | 2 +- drivers/scsi/bfa/bfa_svc.c | 185 +------------------------- drivers/scsi/bfa/bfa_svc.h | 29 ++-- drivers/scsi/bfa/bfad.c | 22 +-- drivers/scsi/bfa/bfad_debugfs.c | 4 +- drivers/scsi/bfa/bfad_im.c | 2 +- 19 files changed, 259 insertions(+), 930 deletions(-) diff --git a/drivers/scsi/bfa/bfa.h b/drivers/scsi/bfa/bfa.h index 7ed13ce6d6aa..6231e5aa55b3 100644 --- a/drivers/scsi/bfa/bfa.h +++ b/drivers/scsi/bfa/bfa.h @@ -296,7 +296,6 @@ void bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev); -void bfa_iocfc_detach(struct bfa_s *bfa); void bfa_iocfc_init(struct bfa_s *bfa); void bfa_iocfc_start(struct bfa_s *bfa); void bfa_iocfc_stop(struct bfa_s *bfa); @@ -385,13 +384,7 @@ void bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, void bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev); -void bfa_init_trc(struct bfa_s *bfa, struct bfa_trc_mod_s *trcmod); -void bfa_init_plog(struct bfa_s *bfa, struct bfa_plog_s *plog); void bfa_detach(struct bfa_s *bfa); -void bfa_init(struct bfa_s *bfa); -void bfa_start(struct bfa_s *bfa); -void bfa_stop(struct bfa_s *bfa); -void bfa_attach_fcs(struct bfa_s *bfa); void bfa_cb_init(void *bfad, bfa_status_t status); void bfa_cb_updateq(void *bfad, bfa_status_t status); @@ -405,7 +398,6 @@ void bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q); typedef void (*bfa_cb_ioc_t) (void *cbarg, enum bfa_status status); void bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr); -void bfa_get_attr(struct bfa_s *bfa, struct bfa_ioc_attr_s *ioc_attr); bfa_status_t bfa_iocfc_israttr_set(struct bfa_s *bfa, @@ -413,16 +405,7 @@ bfa_status_t bfa_iocfc_israttr_set(struct bfa_s *bfa, void bfa_iocfc_enable(struct bfa_s *bfa); void bfa_iocfc_disable(struct bfa_s *bfa); -void bfa_timer_tick(struct bfa_s *bfa); #define bfa_timer_start(_bfa, _timer, _timercb, _arg, _timeout) \ bfa_timer_begin(&(_bfa)->timer_mod, _timer, _timercb, _arg, _timeout) -/* - * BFA debug API functions - */ -bfa_status_t bfa_debug_fwtrc(struct bfa_s *bfa, void *trcdata, int *trclen); -bfa_status_t bfa_debug_fwsave(struct bfa_s *bfa, void *trcdata, int *trclen); -bfa_status_t bfa_debug_fwcore(struct bfa_s *bfa, void *buf, - u32 *offset, int *buflen); - #endif /* __BFA_H__ */ diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c index 90e0f81ae425..002907c694af 100644 --- a/drivers/scsi/bfa/bfa_core.c +++ b/drivers/scsi/bfa/bfa_core.c @@ -66,18 +66,6 @@ static struct bfa_ioc_cbfn_s bfa_iocfc_cbfn; /* * BFA Interrupt handling functions */ -static void -bfa_msix_errint(struct bfa_s *bfa, u32 intr) -{ - bfa_ioc_error_isr(&bfa->ioc); -} - -static void -bfa_msix_lpu(struct bfa_s *bfa) -{ - bfa_ioc_mbox_isr(&bfa->ioc); -} - static void bfa_reqq_resume(struct bfa_s *bfa, int qid) { @@ -267,7 +255,7 @@ bfa_msix_lpu_err(struct bfa_s *bfa, int vec) intr = readl(bfa->iocfc.bfa_regs.intr_status); if (intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1)) - bfa_msix_lpu(bfa); + bfa_ioc_mbox_isr(&bfa->ioc); intr &= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 | __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS | __HFN_INT_LL_HALT); @@ -298,7 +286,7 @@ bfa_msix_lpu_err(struct bfa_s *bfa, int vec) } writel(intr, bfa->iocfc.bfa_regs.intr_status); - bfa_msix_errint(bfa, intr); + bfa_ioc_error_isr(&bfa->ioc); } } @@ -467,8 +455,8 @@ bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg, * First allocate dma memory for IOC. */ bfa_ioc_mem_claim(&bfa->ioc, dm_kva, dm_pa); - dm_kva += bfa_ioc_meminfo(); - dm_pa += bfa_ioc_meminfo(); + dm_kva += BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ); + dm_pa += BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ); /* * Claim DMA-able memory for the request/response queues and for shadow @@ -531,7 +519,7 @@ bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg, bfa_meminfo_dma_virt(meminfo) = dm_kva; bfa_meminfo_dma_phys(meminfo) = dm_pa; - dbgsz = bfa_ioc_debug_trcsz(bfa_auto_recover); + dbgsz = (bfa_auto_recover) ? BFA_DBG_FWTRC_LEN : 0; if (dbgsz > 0) { bfa_ioc_debug_memclaim(&bfa->ioc, bfa_meminfo_kva(meminfo)); bfa_meminfo_kva(meminfo) += dbgsz; @@ -723,11 +711,11 @@ bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len, u32 *dm_len) { /* dma memory for IOC */ - *dm_len += bfa_ioc_meminfo(); + *dm_len += BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ); bfa_iocfc_fw_cfg_sz(cfg, dm_len); bfa_iocfc_cqs_sz(cfg, dm_len); - *km_len += bfa_ioc_debug_trcsz(bfa_auto_recover); + *km_len += (bfa_auto_recover) ? BFA_DBG_FWTRC_LEN : 0; } /* @@ -759,22 +747,13 @@ bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, bfa_iocfc_init_mem(bfa, bfad, cfg, pcidev); bfa_iocfc_mem_claim(bfa, cfg, meminfo); - bfa_timer_init(&bfa->timer_mod); + INIT_LIST_HEAD(&bfa->timer_mod.timer_q); INIT_LIST_HEAD(&bfa->comp_q); for (i = 0; i < BFI_IOC_MAX_CQS; i++) INIT_LIST_HEAD(&bfa->reqq_waitq[i]); } -/* - * Query IOC memory requirement information. - */ -void -bfa_iocfc_detach(struct bfa_s *bfa) -{ - bfa_ioc_detach(&bfa->ioc); -} - /* * Query IOC memory requirement information. */ @@ -1090,79 +1069,7 @@ bfa_detach(struct bfa_s *bfa) for (i = 0; hal_mods[i]; i++) hal_mods[i]->detach(bfa); - - bfa_iocfc_detach(bfa); -} - - -void -bfa_init_trc(struct bfa_s *bfa, struct bfa_trc_mod_s *trcmod) -{ - bfa->trcmod = trcmod; -} - -void -bfa_init_plog(struct bfa_s *bfa, struct bfa_plog_s *plog) -{ - bfa->plog = plog; -} - -/* - * Initialize IOC. - * - * This function will return immediately, when the IOC initialization is - * completed, the bfa_cb_init() will be called. - * - * @param[in] bfa instance - * - * @return void - * - * Special Considerations: - * - * @note - * When this function returns, the driver should register the interrupt service - * routine(s) and enable the device interrupts. If this is not done, - * bfa_cb_init() will never get called - */ -void -bfa_init(struct bfa_s *bfa) -{ - bfa_iocfc_init(bfa); -} - -/* - * Use this function initiate the IOC configuration setup. This function - * will return immediately. - * - * @param[in] bfa instance - * - * @return None - */ -void -bfa_start(struct bfa_s *bfa) -{ - bfa_iocfc_start(bfa); -} - -/* - * Use this function quiese the IOC. This function will return immediately, - * when the IOC is actually stopped, the bfad->comp will be set. - * - * @param[in]bfa - pointer to bfa_t. - * - * @return None - * - * Special Considerations: - * bfad->comp can be set before or after bfa_stop() returns. - * - * @note - * In case of any failure, we could handle it automatically by doing a - * reset and then succeed the bfa_stop() call. - */ -void -bfa_stop(struct bfa_s *bfa) -{ - bfa_iocfc_stop(bfa); + bfa_ioc_detach(&bfa->ioc); } void @@ -1198,20 +1105,6 @@ bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q) } } -void -bfa_attach_fcs(struct bfa_s *bfa) -{ - bfa->fcs = BFA_TRUE; -} - -/* - * Periodic timer heart beat from driver - */ -void -bfa_timer_tick(struct bfa_s *bfa) -{ - bfa_timer_beat(&bfa->timer_mod); -} /* * Return the list of PCI vendor/device id lists supported by this @@ -1282,51 +1175,3 @@ bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg) cfg->drvcfg.num_rspq_elems = BFA_RSPQ_NELEMS_MIN; cfg->drvcfg.min_cfg = BFA_TRUE; } - -void -bfa_get_attr(struct bfa_s *bfa, struct bfa_ioc_attr_s *ioc_attr) -{ - bfa_ioc_get_attr(&bfa->ioc, ioc_attr); -} - -/* - * Retrieve firmware trace information on IOC failure. - */ -bfa_status_t -bfa_debug_fwsave(struct bfa_s *bfa, void *trcdata, int *trclen) -{ - return bfa_ioc_debug_fwsave(&bfa->ioc, trcdata, trclen); -} - -/* - * Fetch firmware trace data. - * - * @param[in] bfa BFA instance - * @param[out] trcdata Firmware trace buffer - * @param[in,out] trclen Firmware trace buffer len - * - * @retval BFA_STATUS_OK Firmware trace is fetched. - * @retval BFA_STATUS_INPROGRESS Firmware trace fetch is in progress. - */ -bfa_status_t -bfa_debug_fwtrc(struct bfa_s *bfa, void *trcdata, int *trclen) -{ - return bfa_ioc_debug_fwtrc(&bfa->ioc, trcdata, trclen); -} - -/* - * Dump firmware memory. - * - * @param[in] bfa BFA instance - * @param[out] buf buffer for dump - * @param[in,out] offset smem offset to start read - * @param[in,out] buflen length of buffer - * - * @retval BFA_STATUS_OK Firmware memory is dumped. - * @retval BFA_STATUS_INPROGRESS Firmware memory dump is in progress. - */ -bfa_status_t -bfa_debug_fwcore(struct bfa_s *bfa, void *buf, u32 *offset, int *buflen) -{ - return bfa_ioc_debug_fwcore(&bfa->ioc, buf, offset, buflen); -} diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c index 0e7f3807dba2..d6aea5d4425f 100644 --- a/drivers/scsi/bfa/bfa_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcpim.c @@ -2567,7 +2567,7 @@ bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim) } bfa_itnim_iodone(ioim->itnim); } else - bfa_tskim_iodone(ioim->iosp->tskim); + bfa_wc_down(&ioim->iosp->tskim->wc); } static bfa_boolean_t diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c index 5b561bde2264..141215c51635 100644 --- a/drivers/scsi/bfa/bfa_fcs.c +++ b/drivers/scsi/bfa/bfa_fcs.c @@ -76,7 +76,7 @@ bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad, fcs->bfad = bfad; fcs->min_cfg = min_cfg; - bfa_attach_fcs(bfa); + bfa->fcs = BFA_TRUE; fcbuild_init(); for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) { @@ -110,14 +110,6 @@ bfa_fcs_init(struct bfa_fcs_s *fcs) } } -/* - * Start FCS operations. - */ -void -bfa_fcs_start(struct bfa_fcs_s *fcs) -{ - bfa_fcs_fabric_modstart(fcs); -} /* * brief @@ -138,22 +130,6 @@ bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs, bfa_fcs_fabric_psymb_init(&fcs->fabric); } -/* - * brief - * FCS FDMI Driver Parameter Initialization - * - * param[in] fcs FCS instance - * param[in] fdmi_enable TRUE/FALSE - * - * return None - */ -void -bfa_fcs_set_fdmi_param(struct bfa_fcs_s *fcs, bfa_boolean_t fdmi_enable) -{ - - fcs->fdmi_enabled = fdmi_enable; - -} /* * brief * FCS instance cleanup and exit. @@ -184,18 +160,6 @@ bfa_fcs_exit(struct bfa_fcs_s *fcs) } -void -bfa_fcs_trc_init(struct bfa_fcs_s *fcs, struct bfa_trc_mod_s *trcmod) -{ - fcs->trcmod = trcmod; -} - -void -bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs) -{ - bfa_wc_down(&fcs->wc); -} - /* * Fabric module implementation. */ @@ -232,31 +196,6 @@ static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg, u32 rsp_len, u32 resid_len, struct fchs_s *rspfchs); -/* - * fcs_fabric_sm fabric state machine functions - */ - -/* - * Fabric state machine events - */ -enum bfa_fcs_fabric_event { - BFA_FCS_FABRIC_SM_CREATE = 1, /* create from driver */ - BFA_FCS_FABRIC_SM_DELETE = 2, /* delete from driver */ - BFA_FCS_FABRIC_SM_LINK_DOWN = 3, /* link down from port */ - BFA_FCS_FABRIC_SM_LINK_UP = 4, /* link up from port */ - BFA_FCS_FABRIC_SM_CONT_OP = 5, /* flogi/auth continue op */ - BFA_FCS_FABRIC_SM_RETRY_OP = 6, /* flogi/auth retry op */ - BFA_FCS_FABRIC_SM_NO_FABRIC = 7, /* from flogi/auth */ - BFA_FCS_FABRIC_SM_PERF_EVFP = 8, /* from flogi/auth */ - BFA_FCS_FABRIC_SM_ISOLATE = 9, /* from EVFP processing */ - BFA_FCS_FABRIC_SM_NO_TAGGING = 10, /* no VFT tagging from EVFP */ - BFA_FCS_FABRIC_SM_DELAYED = 11, /* timeout delay event */ - BFA_FCS_FABRIC_SM_AUTH_FAILED = 12, /* auth failed */ - BFA_FCS_FABRIC_SM_AUTH_SUCCESS = 13, /* auth successful */ - BFA_FCS_FABRIC_SM_DELCOMP = 14, /* all vports deleted event */ - BFA_FCS_FABRIC_SM_LOOPBACK = 15, /* Received our own FLOGI */ - BFA_FCS_FABRIC_SM_START = 16, /* from driver */ -}; static void bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric, enum bfa_fcs_fabric_event event); @@ -270,14 +209,8 @@ static void bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric, enum bfa_fcs_fabric_event event); static void bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric, enum bfa_fcs_fabric_event event); -static void bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric, - enum bfa_fcs_fabric_event event); -static void bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric, - enum bfa_fcs_fabric_event event); static void bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric, enum bfa_fcs_fabric_event event); -static void bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric, - enum bfa_fcs_fabric_event event); static void bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric, enum bfa_fcs_fabric_event event); static void bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric, @@ -337,7 +270,7 @@ bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric, case BFA_FCS_FABRIC_SM_DELETE: bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit); - bfa_fcs_modexit_comp(fabric->fcs); + bfa_wc_down(&fabric->fcs->wc); break; default: @@ -410,7 +343,7 @@ bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric, case BFA_FCS_FABRIC_SM_LOOPBACK: bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_loopback); - bfa_lps_discard(fabric->lps); + bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE); bfa_fcs_fabric_set_opertype(fabric); break; @@ -424,12 +357,12 @@ bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric, case BFA_FCS_FABRIC_SM_LINK_DOWN: bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); - bfa_lps_discard(fabric->lps); + bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE); break; case BFA_FCS_FABRIC_SM_DELETE: bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); - bfa_lps_discard(fabric->lps); + bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE); bfa_fcs_fabric_delete(fabric); break; @@ -481,7 +414,7 @@ bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric, switch (event) { case BFA_FCS_FABRIC_SM_AUTH_FAILED: bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed); - bfa_lps_discard(fabric->lps); + bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE); break; case BFA_FCS_FABRIC_SM_AUTH_SUCCESS: @@ -495,7 +428,7 @@ bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric, case BFA_FCS_FABRIC_SM_LINK_DOWN: bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); - bfa_lps_discard(fabric->lps); + bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE); break; case BFA_FCS_FABRIC_SM_DELETE: @@ -511,7 +444,7 @@ bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric, /* * Authentication failed */ -static void +void bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric, enum bfa_fcs_fabric_event event) { @@ -537,7 +470,7 @@ bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric, /* * Port is in loopback mode. */ -static void +void bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric, enum bfa_fcs_fabric_event event) { @@ -573,7 +506,7 @@ bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric, switch (event) { case BFA_FCS_FABRIC_SM_LINK_DOWN: bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); - bfa_lps_discard(fabric->lps); + bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE); bfa_fcs_fabric_notify_offline(fabric); break; @@ -596,7 +529,7 @@ bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric, /* * Fabric is online - normal operating state. */ -static void +void bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric, enum bfa_fcs_fabric_event event) { @@ -606,7 +539,7 @@ bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric, switch (event) { case BFA_FCS_FABRIC_SM_LINK_DOWN: bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); - bfa_lps_discard(fabric->lps); + bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE); bfa_fcs_fabric_notify_offline(fabric); break; @@ -617,7 +550,7 @@ bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric, case BFA_FCS_FABRIC_SM_AUTH_FAILED: bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed); - bfa_lps_discard(fabric->lps); + bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE); break; case BFA_FCS_FABRIC_SM_AUTH_SUCCESS: @@ -697,7 +630,7 @@ bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric, switch (event) { case BFA_FCS_FABRIC_SM_DELCOMP: bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit); - bfa_fcs_modexit_comp(fabric->fcs); + bfa_wc_down(&fabric->fcs->wc); break; case BFA_FCS_FABRIC_SM_LINK_UP: @@ -724,8 +657,8 @@ bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric) struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg; port_cfg->roles = BFA_LPORT_ROLE_FCP_IM; - port_cfg->nwwn = bfa_ioc_get_nwwn(&fabric->fcs->bfa->ioc); - port_cfg->pwwn = bfa_ioc_get_pwwn(&fabric->fcs->bfa->ioc); + port_cfg->nwwn = fabric->fcs->bfa->ioc.attr->nwwn; + port_cfg->pwwn = fabric->fcs->bfa->ioc.attr->pwwn; } /* @@ -813,7 +746,7 @@ bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status) return; case BFA_STATUS_EPROTOCOL: - switch (bfa_lps_get_extstatus(fabric->lps)) { + switch (fabric->lps->ext_status) { case BFA_EPROTO_BAD_ACCEPT: fabric->stats.flogi_acc_err++; break; @@ -840,26 +773,26 @@ bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status) return; } - fabric->bb_credit = bfa_lps_get_peer_bbcredit(fabric->lps); + fabric->bb_credit = fabric->lps->pr_bbcred; bfa_trc(fabric->fcs, fabric->bb_credit); - if (!bfa_lps_is_brcd_fabric(fabric->lps)) - fabric->fabric_name = bfa_lps_get_peer_nwwn(fabric->lps); + if (!(fabric->lps->brcd_switch)) + fabric->fabric_name = fabric->lps->pr_nwwn; /* * Check port type. It should be 1 = F-port. */ - if (bfa_lps_is_fport(fabric->lps)) { - fabric->bport.pid = bfa_lps_get_pid(fabric->lps); - fabric->is_npiv = bfa_lps_is_npiv_en(fabric->lps); - fabric->is_auth = bfa_lps_is_authreq(fabric->lps); + if (fabric->lps->fport) { + fabric->bport.pid = fabric->lps->lp_pid; + fabric->is_npiv = fabric->lps->npiv_en; + fabric->is_auth = fabric->lps->auth_req; bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_CONT_OP); } else { /* * Nport-2-Nport direct attached */ fabric->bport.port_topo.pn2n.rem_port_wwn = - bfa_lps_get_peer_pwwn(fabric->lps); + fabric->lps->pr_pwwn; bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC); } @@ -1038,23 +971,6 @@ bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs) bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_START); } -bfa_boolean_t -bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric) -{ - return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_loopback); -} - -bfa_boolean_t -bfa_fcs_fabric_is_auth_failed(struct bfa_fcs_fabric_s *fabric) -{ - return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_auth_failed); -} - -enum bfa_port_type -bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric) -{ - return fabric->oper_type; -} /* * Link up notification from BFA physical port module. @@ -1115,28 +1031,6 @@ bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric, bfa_wc_down(&fabric->wc); } -/* - * Base port is deleted. - */ -void -bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric) -{ - bfa_wc_down(&fabric->wc); -} - - -/* - * Check if fabric is online. - * - * param[in] fabric - Fabric instance. This can be a base fabric or vf. - * - * @return TRUE/FALSE - */ -int -bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric) -{ - return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_online); -} /* * Lookup for a vport withing a fabric given its pwwn @@ -1156,18 +1050,6 @@ bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s *fabric, wwn_t pwwn) return NULL; } -/* - * In a given fabric, return the number of lports. - * - * param[in] fabric - Fabric instance. This can be a base fabric or vf. - * - * @return : 1 or more. - */ -u16 -bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric) -{ - return fabric->num_vports; -} /* * Get OUI of the attached switch. @@ -1187,7 +1069,7 @@ bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric) u8 *tmp; u16 oui; - fab_nwwn = bfa_lps_get_peer_nwwn(fabric->lps); + fab_nwwn = fabric->lps->pr_nwwn; tmp = (u8 *)&fab_nwwn; oui = (tmp[3] << 8) | tmp[4]; @@ -1344,7 +1226,7 @@ bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric) bfa_fcport_get_maxfrsize(bfa), bfa_fcport_get_rx_bbcredit(bfa)); - bfa_fcxp_send(fcxp, NULL, fabric->vf_id, bfa_lps_get_tag(fabric->lps), + bfa_fcxp_send(fcxp, NULL, fabric->vf_id, fabric->lps->lp_tag, BFA_FALSE, FC_CLASS_3, reqlen, &fchs, bfa_fcs_fabric_flogiacc_comp, fabric, FC_MAX_PDUSZ, 0); diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h index fcb54e5ef331..e7977ee32992 100644 --- a/drivers/scsi/bfa/bfa_fcs.h +++ b/drivers/scsi/bfa/bfa_fcs.h @@ -26,6 +26,21 @@ #define BFA_FCS_OS_STR_LEN 64 +/* + * lps_pvt BFA LPS private functions + */ + +enum bfa_lps_event { + BFA_LPS_SM_LOGIN = 1, /* login request from user */ + BFA_LPS_SM_LOGOUT = 2, /* logout request from user */ + BFA_LPS_SM_FWRSP = 3, /* f/w response to login/logout */ + BFA_LPS_SM_RESUME = 4, /* space present in reqq queue */ + BFA_LPS_SM_DELETE = 5, /* lps delete from user */ + BFA_LPS_SM_OFFLINE = 6, /* Link is offline */ + BFA_LPS_SM_RX_CVL = 7, /* Rx clear virtual link */ +}; + + /* * !!! Only append to the enums defined here to avoid any versioning * !!! needed between trace utility and driver version @@ -41,7 +56,6 @@ enum { struct bfa_fcs_s; #define __fcs_min_cfg(__fcs) ((__fcs)->min_cfg) -void bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs); #define BFA_FCS_BRCD_SWITCH_OUI 0x051e #define N2N_LOCAL_PID 0x010000 @@ -444,9 +458,6 @@ void bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport); struct bfa_fcs_rport_s *bfa_fcs_rport_create(struct bfa_fcs_lport_s *port, u32 pid); -void bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport); -void bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport); -void bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport); void bfa_fcs_rport_start(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs, struct fc_logi_s *plogi_rsp); void bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port, @@ -454,10 +465,8 @@ void bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port, struct fc_logi_s *plogi); void bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs, struct fc_logi_s *plogi); -void bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport); void bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, __be16 ox_id); -void bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport); void bfa_fcs_rport_itntm_ack(struct bfa_fcs_rport_s *rport); void bfa_fcs_rport_fcptm_offline_done(struct bfa_fcs_rport_s *rport); int bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport); @@ -647,6 +656,57 @@ struct bfa_fcs_s { struct bfa_wc_s wc; /* waiting counter */ }; +/* + * fcs_fabric_sm fabric state machine functions + */ + +/* + * Fabric state machine events + */ +enum bfa_fcs_fabric_event { + BFA_FCS_FABRIC_SM_CREATE = 1, /* create from driver */ + BFA_FCS_FABRIC_SM_DELETE = 2, /* delete from driver */ + BFA_FCS_FABRIC_SM_LINK_DOWN = 3, /* link down from port */ + BFA_FCS_FABRIC_SM_LINK_UP = 4, /* link up from port */ + BFA_FCS_FABRIC_SM_CONT_OP = 5, /* flogi/auth continue op */ + BFA_FCS_FABRIC_SM_RETRY_OP = 6, /* flogi/auth retry op */ + BFA_FCS_FABRIC_SM_NO_FABRIC = 7, /* from flogi/auth */ + BFA_FCS_FABRIC_SM_PERF_EVFP = 8, /* from flogi/auth */ + BFA_FCS_FABRIC_SM_ISOLATE = 9, /* from EVFP processing */ + BFA_FCS_FABRIC_SM_NO_TAGGING = 10, /* no VFT tagging from EVFP */ + BFA_FCS_FABRIC_SM_DELAYED = 11, /* timeout delay event */ + BFA_FCS_FABRIC_SM_AUTH_FAILED = 12, /* auth failed */ + BFA_FCS_FABRIC_SM_AUTH_SUCCESS = 13, /* auth successful */ + BFA_FCS_FABRIC_SM_DELCOMP = 14, /* all vports deleted event */ + BFA_FCS_FABRIC_SM_LOOPBACK = 15, /* Received our own FLOGI */ + BFA_FCS_FABRIC_SM_START = 16, /* from driver */ +}; + +/* + * fcs_rport_sm FCS rport state machine events + */ + +enum rport_event { + RPSM_EVENT_PLOGI_SEND = 1, /* new rport; start with PLOGI */ + RPSM_EVENT_PLOGI_RCVD = 2, /* Inbound PLOGI from remote port */ + RPSM_EVENT_PLOGI_COMP = 3, /* PLOGI completed to rport */ + RPSM_EVENT_LOGO_RCVD = 4, /* LOGO from remote device */ + RPSM_EVENT_LOGO_IMP = 5, /* implicit logo for SLER */ + RPSM_EVENT_FCXP_SENT = 6, /* Frame from has been sent */ + RPSM_EVENT_DELETE = 7, /* RPORT delete request */ + RPSM_EVENT_SCN = 8, /* state change notification */ + RPSM_EVENT_ACCEPTED = 9, /* Good response from remote device */ + RPSM_EVENT_FAILED = 10, /* Request to rport failed. */ + RPSM_EVENT_TIMEOUT = 11, /* Rport SM timeout event */ + RPSM_EVENT_HCB_ONLINE = 12, /* BFA rport online callback */ + RPSM_EVENT_HCB_OFFLINE = 13, /* BFA rport offline callback */ + RPSM_EVENT_FC4_OFFLINE = 14, /* FC-4 offline complete */ + RPSM_EVENT_ADDRESS_CHANGE = 15, /* Rport's PID has changed */ + RPSM_EVENT_ADDRESS_DISC = 16, /* Need to Discover rport's PID */ + RPSM_EVENT_PRLO_RCVD = 17, /* PRLO from remote device */ + RPSM_EVENT_PLOGI_RETRY = 18, /* Retry PLOGI continously */ +}; + /* * bfa fcs API functions */ @@ -656,16 +716,12 @@ void bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, void bfa_fcs_init(struct bfa_fcs_s *fcs); void bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs, struct bfa_fcs_driver_info_s *driver_info); -void bfa_fcs_set_fdmi_param(struct bfa_fcs_s *fcs, bfa_boolean_t fdmi_enable); void bfa_fcs_exit(struct bfa_fcs_s *fcs); -void bfa_fcs_trc_init(struct bfa_fcs_s *fcs, struct bfa_trc_mod_s *trcmod); -void bfa_fcs_start(struct bfa_fcs_s *fcs); /* * bfa fcs vf public functions */ bfa_fcs_vf_t *bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id); -u16 bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric); /* * fabric protected interface functions @@ -679,22 +735,23 @@ void bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric, struct bfa_fcs_vport_s *vport); void bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric, struct bfa_fcs_vport_s *vport); -int bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric); struct bfa_fcs_vport_s *bfa_fcs_fabric_vport_lookup( struct bfa_fcs_fabric_s *fabric, wwn_t pwwn); void bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs); void bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs, u16 len); -bfa_boolean_t bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric); -bfa_boolean_t bfa_fcs_fabric_is_auth_failed(struct bfa_fcs_fabric_s *fabric); -enum bfa_port_type bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric); void bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric); -void bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric); void bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric, wwn_t fabric_name); u16 bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric); void bfa_fcs_uf_attach(struct bfa_fcs_s *fcs); void bfa_fcs_port_attach(struct bfa_fcs_s *fcs); +void bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric, + enum bfa_fcs_fabric_event event); +void bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric, + enum bfa_fcs_fabric_event event); +void bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric, + enum bfa_fcs_fabric_event event); /* * BFA FCS callback interfaces diff --git a/drivers/scsi/bfa/bfa_fcs_fcpim.c b/drivers/scsi/bfa/bfa_fcs_fcpim.c index 413b58eef93a..82ac2798c545 100644 --- a/drivers/scsi/bfa/bfa_fcs_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcs_fcpim.c @@ -103,7 +103,7 @@ bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim, break; case BFA_FCS_ITNIM_SM_OFFLINE: - bfa_fcs_rport_itnim_ack(itnim->rport); + bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE); break; case BFA_FCS_ITNIM_SM_INITIATOR: @@ -140,7 +140,7 @@ bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim, case BFA_FCS_ITNIM_SM_OFFLINE: bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe); - bfa_fcs_rport_itnim_ack(itnim->rport); + bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE); break; case BFA_FCS_ITNIM_SM_DELETE: @@ -181,7 +181,7 @@ bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim, case BFA_FCS_ITNIM_SM_OFFLINE: bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); bfa_fcxp_discard(itnim->fcxp); - bfa_fcs_rport_itnim_ack(itnim->rport); + bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE); break; case BFA_FCS_ITNIM_SM_INITIATOR: @@ -217,7 +217,7 @@ bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim, } else { /* invoke target offline */ bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); - bfa_fcs_rport_logo_imp(itnim->rport); + bfa_sm_send_event(itnim->rport, RPSM_EVENT_LOGO_IMP); } break; @@ -225,7 +225,7 @@ bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim, case BFA_FCS_ITNIM_SM_OFFLINE: bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); bfa_timer_stop(&itnim->timer); - bfa_fcs_rport_itnim_ack(itnim->rport); + bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE); break; case BFA_FCS_ITNIM_SM_INITIATOR: @@ -269,7 +269,7 @@ bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim, case BFA_FCS_ITNIM_SM_OFFLINE: bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); bfa_itnim_offline(itnim->bfa_itnim); - bfa_fcs_rport_itnim_ack(itnim->rport); + bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE); break; case BFA_FCS_ITNIM_SM_DELETE: @@ -330,7 +330,7 @@ bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim, switch (event) { case BFA_FCS_ITNIM_SM_HCB_OFFLINE: bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); - bfa_fcs_rport_itnim_ack(itnim->rport); + bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE); break; case BFA_FCS_ITNIM_SM_DELETE: @@ -358,7 +358,7 @@ bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim, switch (event) { case BFA_FCS_ITNIM_SM_OFFLINE: bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); - bfa_fcs_rport_itnim_ack(itnim->rport); + bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE); break; case BFA_FCS_ITNIM_SM_RSP_ERROR: @@ -688,7 +688,7 @@ bfa_cb_itnim_sler(void *cb_arg) itnim->stats.sler++; bfa_trc(itnim->fcs, itnim->rport->pwwn); - bfa_fcs_rport_logo_imp(itnim->rport); + bfa_sm_send_event(itnim->rport, RPSM_EVENT_LOGO_IMP); } struct bfa_fcs_itnim_s * diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c index bd0c093fca66..6e9151fecb74 100644 --- a/drivers/scsi/bfa/bfa_fcs_lport.c +++ b/drivers/scsi/bfa/bfa_fcs_lport.c @@ -159,7 +159,7 @@ bfa_fcs_lport_sm_online( bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting); list_for_each_safe(qe, qen, &port->rport_q) { rport = (struct bfa_fcs_rport_s *) qe; - bfa_fcs_rport_delete(rport); + bfa_sm_send_event(rport, RPSM_EVENT_DELETE); } } break; @@ -197,7 +197,7 @@ bfa_fcs_lport_sm_offline( bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting); list_for_each_safe(qe, qen, &port->rport_q) { rport = (struct bfa_fcs_rport_s *) qe; - bfa_fcs_rport_delete(rport); + bfa_sm_send_event(rport, RPSM_EVENT_DELETE); } } break; @@ -350,7 +350,7 @@ bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port, * disappeared. Send implicit LOGO to old device. */ bfa_assert(rport->pwwn != plogi->port_name); - bfa_fcs_rport_logo_imp(rport); + bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP); /* * Inbound PLOGI from a new device (with old PID). @@ -511,7 +511,8 @@ bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port) __port_action[port->fabric->fab_type].offline(port); wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port)); - if (bfa_fcs_fabric_is_online(port->fabric) == BFA_TRUE) + if (bfa_sm_cmp_state(port->fabric, + bfa_fcs_fabric_sm_online) == BFA_TRUE) BFA_LOG(KERN_ERR, bfad, bfa_log_level, "Logical port lost fabric connectivity: WWN = %s Role = %s\n", lpwwn_buf, "Initiator"); @@ -522,7 +523,7 @@ bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port) list_for_each_safe(qe, qen, &port->rport_q) { rport = (struct bfa_fcs_rport_s *) qe; - bfa_fcs_rport_offline(rport); + bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP); } } @@ -584,7 +585,7 @@ bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port) port->vport ? port->vport->vport_drv : NULL); bfa_fcs_vport_delete_comp(port->vport); } else { - bfa_fcs_fabric_port_delete_comp(port->fabric); + bfa_wc_down(&port->fabric->wc); } } @@ -828,8 +829,8 @@ bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs, lport->fcs = fcs; lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id); lport->vport = vport; - lport->lp_tag = (vport) ? bfa_lps_get_tag(vport->lps) : - bfa_lps_get_tag(lport->fabric->lps); + lport->lp_tag = (vport) ? vport->lps->lp_tag : + lport->fabric->lps->lp_tag; INIT_LIST_HEAD(&lport->rport_q); lport->num_rports = 0; @@ -881,10 +882,11 @@ bfa_fcs_lport_get_attr( port_attr->port_cfg = port->port_cfg; if (port->fabric) { - port_attr->port_type = bfa_fcs_fabric_port_type(port->fabric); - port_attr->loopback = bfa_fcs_fabric_is_loopback(port->fabric); + port_attr->port_type = port->fabric->oper_type; + port_attr->loopback = bfa_sm_cmp_state(port->fabric, bfa_fcs_fabric_sm_loopback); port_attr->authfail = - bfa_fcs_fabric_is_auth_failed(port->fabric); + bfa_sm_cmp_state(port->fabric, + bfa_fcs_fabric_sm_auth_failed); port_attr->fabric_name = bfa_fcs_lport_get_fabric_name(port); memcpy(port_attr->fabric_ip_addr, bfa_fcs_lport_get_fabric_ipaddr(port), @@ -893,10 +895,10 @@ bfa_fcs_lport_get_attr( if (port->vport != NULL) { port_attr->port_type = BFA_PORT_TYPE_VPORT; port_attr->fpma_mac = - bfa_lps_get_lp_mac(port->vport->lps); + port->vport->lps->lp_mac; } else { port_attr->fpma_mac = - bfa_lps_get_lp_mac(port->fabric->lps); + port->fabric->lps->lp_mac; } } else { port_attr->port_type = BFA_PORT_TYPE_UNKNOWN; @@ -985,7 +987,7 @@ bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port) bfa_trc(port->fcs, rport->pid); bfa_trc(port->fcs, rport->pwwn); rport->pid = N2N_REMOTE_PID; - bfa_fcs_rport_online(rport); + bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND); return; } @@ -998,7 +1000,7 @@ bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port) bfa_assert(rport != NULL); if (rport) { bfa_trc(port->fcs, rport->pwwn); - bfa_fcs_rport_delete(rport); + bfa_sm_send_event(rport, RPSM_EVENT_DELETE); } } bfa_fcs_rport_create(port, N2N_REMOTE_PID); @@ -2540,7 +2542,7 @@ bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced) len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), bfa_fcs_lport_get_fcid(port), - bfa_lps_get_peer_nwwn(port->fabric->lps)); + port->fabric->lps->pr_nwwn); bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, @@ -2740,7 +2742,7 @@ bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced) len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), bfa_fcs_lport_get_fcid(port), - bfa_lps_get_peer_nwwn(port->fabric->lps)); + port->fabric->lps->pr_nwwn); bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, @@ -4332,8 +4334,8 @@ bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced) /* Handle VU registrations for Base port only */ if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) { len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), - bfa_lps_is_brcd_fabric(port->fabric->lps), - port->pid, 0); + port->fabric->lps->brcd_switch, + port->pid, 0); } else { len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), BFA_FALSE, @@ -4833,7 +4835,7 @@ bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port, port_info->max_vports_supp = bfa_lps_get_max_vport(port->fcs->bfa); port_info->num_vports_inuse = - bfa_fcs_fabric_vport_count(port->fabric); + port->fabric->num_vports; port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP; port_info->num_rports_inuse = port->num_rports; } else { @@ -4977,7 +4979,8 @@ bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport, switch (event) { case BFA_FCS_VPORT_SM_START: - if (bfa_fcs_fabric_is_online(__vport_fabric(vport)) + if (bfa_sm_cmp_state(__vport_fabric(vport), + bfa_fcs_fabric_sm_online) && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) { bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc); bfa_fcs_vport_do_fdisc(vport); @@ -5060,13 +5063,13 @@ bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport, switch (event) { case BFA_FCS_VPORT_SM_DELETE: bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); - bfa_lps_discard(vport->lps); + bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE); bfa_fcs_lport_delete(&vport->lport); break; case BFA_FCS_VPORT_SM_OFFLINE: bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); - bfa_lps_discard(vport->lps); + bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE); break; case BFA_FCS_VPORT_SM_RSP_OK: @@ -5146,7 +5149,7 @@ bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport, case BFA_FCS_VPORT_SM_OFFLINE: bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); - bfa_lps_discard(vport->lps); + bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE); bfa_fcs_lport_offline(&vport->lport); break; @@ -5246,7 +5249,7 @@ bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport, switch (event) { case BFA_FCS_VPORT_SM_OFFLINE: - bfa_lps_discard(vport->lps); + bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE); /* * !!! fall through !!! */ @@ -5285,14 +5288,14 @@ bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport) static void bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport) { - u8 lsrjt_rsn = bfa_lps_get_lsrjt_rsn(vport->lps); - u8 lsrjt_expl = bfa_lps_get_lsrjt_expl(vport->lps); + u8 lsrjt_rsn = vport->lps->lsrjt_rsn; + u8 lsrjt_expl = vport->lps->lsrjt_expl; bfa_trc(__vport_fcs(vport), lsrjt_rsn); bfa_trc(__vport_fcs(vport), lsrjt_expl); /* For certain reason codes, we don't want to retry. */ - switch (bfa_lps_get_lsrjt_expl(vport->lps)) { + switch (vport->lps->lsrjt_expl) { case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */ case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */ if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES) @@ -5456,7 +5459,7 @@ bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs, if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL) return BFA_STATUS_VPORT_EXISTS; - if (bfa_fcs_fabric_vport_count(&fcs->fabric) == + if (fcs->fabric.num_vports == bfa_lps_get_max_vport(fcs->bfa)) return BFA_STATUS_VPORT_MAX; @@ -5637,7 +5640,7 @@ bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status) /* * Initialiaze the V-Port fields */ - __vport_fcid(vport) = bfa_lps_get_pid(vport->lps); + __vport_fcid(vport) = vport->lps->lp_pid; vport->vport_stats.fdisc_accepts++; bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK); break; @@ -5650,7 +5653,7 @@ bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status) break; case BFA_STATUS_EPROTOCOL: - switch (bfa_lps_get_extstatus(vport->lps)) { + switch (vport->lps->ext_status) { case BFA_EPROTO_BAD_ACCEPT: vport->vport_stats.fdisc_acc_bad++; break; diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c index 7928bc8c1ed7..2089d686fa5d 100644 --- a/drivers/scsi/bfa/bfa_fcs_rport.c +++ b/drivers/scsi/bfa/bfa_fcs_rport.c @@ -75,30 +75,6 @@ static void bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, static void bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs, u16 len); static void bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport); -/* - * fcs_rport_sm FCS rport state machine events - */ - -enum rport_event { - RPSM_EVENT_PLOGI_SEND = 1, /* new rport; start with PLOGI */ - RPSM_EVENT_PLOGI_RCVD = 2, /* Inbound PLOGI from remote port */ - RPSM_EVENT_PLOGI_COMP = 3, /* PLOGI completed to rport */ - RPSM_EVENT_LOGO_RCVD = 4, /* LOGO from remote device */ - RPSM_EVENT_LOGO_IMP = 5, /* implicit logo for SLER */ - RPSM_EVENT_FCXP_SENT = 6, /* Frame from has been sent */ - RPSM_EVENT_DELETE = 7, /* RPORT delete request */ - RPSM_EVENT_SCN = 8, /* state change notification */ - RPSM_EVENT_ACCEPTED = 9, /* Good response from remote device */ - RPSM_EVENT_FAILED = 10, /* Request to rport failed. */ - RPSM_EVENT_TIMEOUT = 11, /* Rport SM timeout event */ - RPSM_EVENT_HCB_ONLINE = 12, /* BFA rport online callback */ - RPSM_EVENT_HCB_OFFLINE = 13, /* BFA rport offline callback */ - RPSM_EVENT_FC4_OFFLINE = 14, /* FC-4 offline complete */ - RPSM_EVENT_ADDRESS_CHANGE = 15, /* Rport's PID has changed */ - RPSM_EVENT_ADDRESS_DISC = 16, /* Need to Discover rport's PID */ - RPSM_EVENT_PRLO_RCVD = 17, /* PRLO from remote device */ - RPSM_EVENT_PLOGI_RETRY = 18, /* Retry PLOGI continously */ -}; static void bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event); @@ -498,24 +474,24 @@ bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport, case RPSM_EVENT_LOGO_RCVD: bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv); - bfa_rport_offline(rport->bfa_rport); + bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE); break; case RPSM_EVENT_LOGO_IMP: case RPSM_EVENT_ADDRESS_CHANGE: bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline); - bfa_rport_offline(rport->bfa_rport); + bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE); break; case RPSM_EVENT_PLOGI_RCVD: bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); - bfa_rport_offline(rport->bfa_rport); + bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE); bfa_fcs_rport_send_plogiacc(rport, NULL); break; case RPSM_EVENT_DELETE: bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend); - bfa_rport_offline(rport->bfa_rport); + bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE); break; case RPSM_EVENT_SCN: @@ -824,7 +800,7 @@ bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport, switch (event) { case RPSM_EVENT_FC4_OFFLINE: bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv); - bfa_rport_offline(rport->bfa_rport); + bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE); break; case RPSM_EVENT_DELETE: @@ -856,7 +832,7 @@ bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport, switch (event) { case RPSM_EVENT_FC4_OFFLINE: bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend); - bfa_rport_offline(rport->bfa_rport); + bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE); break; default: @@ -878,7 +854,7 @@ bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport, switch (event) { case RPSM_EVENT_FC4_OFFLINE: bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline); - bfa_rport_offline(rport->bfa_rport); + bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE); break; case RPSM_EVENT_SCN: @@ -1459,7 +1435,7 @@ bfa_fcs_rport_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg, twin->stats.plogi_rcvd += rport->stats.plogi_rcvd; twin->stats.plogi_accs++; - bfa_fcs_rport_delete(rport); + bfa_sm_send_event(rport, RPSM_EVENT_DELETE); bfa_fcs_rport_update(twin, plogi_rsp); twin->pid = rsp_fchs->s_id; @@ -1998,7 +1974,7 @@ bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid) rport->itnim = bfa_fcs_itnim_create(rport); if (!rport->itnim) { bfa_trc(fcs, rpid); - bfa_rport_delete(rport->bfa_rport); + bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_DELETE); kfree(rport_drv); return NULL; } @@ -2032,7 +2008,7 @@ bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport) bfa_fcs_rpf_rport_offline(rport); } - bfa_rport_delete(rport->bfa_rport); + bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_DELETE); bfa_fcs_lport_del_rport(port, rport); kfree(rport->rp_drv); } @@ -2307,39 +2283,7 @@ bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs, bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD); } -/* - * Called by bport/vport to delete a remote port instance. - * - * Rport delete is called under the following conditions: - * - vport is deleted - * - vf is deleted - * - explicit request from OS to delete rport - */ -void -bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport) -{ - bfa_sm_send_event(rport, RPSM_EVENT_DELETE); -} -/* - * Called by bport/vport to when a target goes offline. - * - */ -void -bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport) -{ - bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP); -} - -/* - * Called by bport in n2n when a target (attached port) becomes online. - * - */ -void -bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport) -{ - bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND); -} /* * Called by bport/vport to notify SCN for the remote port */ @@ -2350,15 +2294,6 @@ bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport) bfa_sm_send_event(rport, RPSM_EVENT_SCN); } -/* - * Called by fcpim to notify that the ITN cleanup is done. - */ -void -bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport) -{ - bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE); -} - /* * brief @@ -2453,15 +2388,6 @@ bfa_cb_rport_qos_scn_prio(void *cbarg, bfa_trc(rport->fcs, rport->pwwn); } -/* - * Called to process any unsolicted frames from this remote port - */ -void -bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport) -{ - bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP); -} - /* * Called to process any unsolicted frames from this remote port */ @@ -2578,6 +2504,7 @@ bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport) return bfa_sm_to_state(rport_sm_table, rport->sm); } + /* * brief * Called by the Driver to set rport delete/ageout timeout @@ -2703,7 +2630,7 @@ bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, enum rpf_event event) case RPFSM_EVENT_RPORT_ONLINE: /* Send RPSC2 to a Brocade fabric only. */ if ((!BFA_FCS_PID_IS_WKA(rport->pid)) && - ((bfa_lps_is_brcd_fabric(rport->port->fabric->lps)) || + ((rport->port->fabric->lps->brcd_switch) || (bfa_fcs_fabric_get_switch_oui(fabric) == BFA_FCS_BRCD_SWITCH_OUI))) { bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending); diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index 3f41d290142d..a8f745420f32 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -42,11 +42,6 @@ BFA_TRC_FILE(CNA, IOC); bfa_ioc_hb_check, (__ioc), BFA_IOC_HB_TOV) #define bfa_hb_timer_stop(__ioc) bfa_timer_stop(&(__ioc)->hb_timer) -#define BFA_DBG_FWTRC_ENTS (BFI_IOC_TRC_ENTS) -#define BFA_DBG_FWTRC_LEN \ - (BFA_DBG_FWTRC_ENTS * sizeof(struct bfa_trc_s) + \ - (sizeof(struct bfa_trc_mod_s) - \ - BFA_TRC_MAX * sizeof(struct bfa_trc_s))) #define BFA_DBG_FWTRC_OFF(_fn) (BFI_IOC_TRC_OFF + BFA_DBG_FWTRC_LEN * (_fn)) /* @@ -81,24 +76,18 @@ bfa_boolean_t bfa_auto_recover = BFA_TRUE; * forward declarations */ static void bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc); -static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc); static void bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force); static void bfa_ioc_timeout(void *ioc); static void bfa_ioc_send_enable(struct bfa_ioc_s *ioc); static void bfa_ioc_send_disable(struct bfa_ioc_s *ioc); static void bfa_ioc_send_getattr(struct bfa_ioc_s *ioc); static void bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc); -static void bfa_ioc_hb_stop(struct bfa_ioc_s *ioc); -static void bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force); static void bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc); static void bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc); static void bfa_ioc_recover(struct bfa_ioc_s *ioc); static void bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc); static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc); static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc); -static void bfa_ioc_pf_enabled(struct bfa_ioc_s *ioc); -static void bfa_ioc_pf_disabled(struct bfa_ioc_s *ioc); -static void bfa_ioc_pf_failed(struct bfa_ioc_s *ioc); static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc); @@ -162,12 +151,6 @@ static struct bfa_sm_table_s ioc_sm_table[] = { /* * Forward declareations for iocpf state machine */ -static void bfa_iocpf_enable(struct bfa_ioc_s *ioc); -static void bfa_iocpf_disable(struct bfa_ioc_s *ioc); -static void bfa_iocpf_fail(struct bfa_ioc_s *ioc); -static void bfa_iocpf_initfail(struct bfa_ioc_s *ioc); -static void bfa_iocpf_getattrfail(struct bfa_ioc_s *ioc); -static void bfa_iocpf_stop(struct bfa_ioc_s *ioc); static void bfa_iocpf_timeout(void *ioc_arg); static void bfa_iocpf_sem_timeout(void *ioc_arg); @@ -298,7 +281,7 @@ bfa_ioc_sm_reset(struct bfa_ioc_s *ioc, enum ioc_event event) static void bfa_ioc_sm_enabling_entry(struct bfa_ioc_s *ioc) { - bfa_iocpf_enable(ioc); + bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_ENABLE); } /* @@ -321,7 +304,7 @@ bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event) case IOC_E_HWERROR: bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); - bfa_iocpf_initfail(ioc); + bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL); break; case IOC_E_DISABLE: @@ -330,7 +313,7 @@ bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event) case IOC_E_DETACH: bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit); - bfa_iocpf_stop(ioc); + bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP); break; case IOC_E_ENABLE: @@ -375,7 +358,7 @@ bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event) case IOC_E_TIMEOUT: bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); - bfa_iocpf_getattrfail(ioc); + bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL); break; case IOC_E_DISABLE: @@ -412,22 +395,22 @@ bfa_ioc_sm_op(struct bfa_ioc_s *ioc, enum ioc_event event) break; case IOC_E_DISABLE: - bfa_ioc_hb_stop(ioc); + bfa_hb_timer_stop(ioc); bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling); break; case IOC_E_FAILED: - bfa_ioc_hb_stop(ioc); + bfa_hb_timer_stop(ioc); bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); break; case IOC_E_HWERROR: - bfa_ioc_hb_stop(ioc); + bfa_hb_timer_stop(ioc); /* !!! fall through !!! */ case IOC_E_HBFAIL: bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); - bfa_iocpf_fail(ioc); + bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL); break; default: @@ -440,7 +423,7 @@ static void bfa_ioc_sm_disabling_entry(struct bfa_ioc_s *ioc) { struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad; - bfa_iocpf_disable(ioc); + bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_DISABLE); BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC disabled\n"); } @@ -463,7 +446,7 @@ bfa_ioc_sm_disabling(struct bfa_ioc_s *ioc, enum ioc_event event) * after iocpf sm completes failure processing and * moves to disabled state. */ - bfa_iocpf_fail(ioc); + bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL); break; default: @@ -496,7 +479,7 @@ bfa_ioc_sm_disabled(struct bfa_ioc_s *ioc, enum ioc_event event) case IOC_E_DETACH: bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit); - bfa_iocpf_stop(ioc); + bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP); break; default: @@ -537,7 +520,7 @@ bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event) case IOC_E_DETACH: bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit); - bfa_iocpf_stop(ioc); + bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP); break; default: @@ -668,19 +651,19 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf_s *iocpf, enum iocpf_event event) iocpf->retry_count = 0; bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); } else { - bfa_ioc_hw_sem_release(ioc); + writel(1, ioc->ioc_regs.ioc_sem_reg); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_mismatch); } break; case IOCPF_E_DISABLE: - bfa_ioc_hw_sem_get_cancel(ioc); + bfa_sem_timer_stop(ioc); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset); - bfa_ioc_pf_disabled(ioc); + bfa_fsm_send_event(ioc, IOC_E_DISABLED); break; case IOCPF_E_STOP: - bfa_ioc_hw_sem_get_cancel(ioc); + bfa_sem_timer_stop(ioc); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset); break; @@ -723,7 +706,7 @@ bfa_iocpf_sm_mismatch(struct bfa_iocpf_s *iocpf, enum iocpf_event event) case IOCPF_E_DISABLE: bfa_iocpf_timer_stop(ioc); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset); - bfa_ioc_pf_disabled(ioc); + bfa_fsm_send_event(ioc, IOC_E_DISABLED); break; case IOCPF_E_STOP: @@ -762,7 +745,7 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf_s *iocpf, enum iocpf_event event) break; case IOCPF_E_DISABLE: - bfa_ioc_hw_sem_get_cancel(ioc); + bfa_sem_timer_stop(ioc); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); break; @@ -776,7 +759,7 @@ static void bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf_s *iocpf) { bfa_iocpf_timer_start(iocpf->ioc); - bfa_ioc_reset(iocpf->ioc, BFA_FALSE); + bfa_ioc_hwinit(iocpf->ioc, BFA_FALSE); } /* @@ -806,19 +789,19 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event) iocpf->retry_count++; if (iocpf->retry_count < BFA_IOC_HWINIT_MAX) { bfa_iocpf_timer_start(ioc); - bfa_ioc_reset(ioc, BFA_TRUE); + bfa_ioc_hwinit(ioc, BFA_TRUE); break; } - bfa_ioc_hw_sem_release(ioc); + writel(1, ioc->ioc_regs.ioc_sem_reg); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); if (event == IOCPF_E_TIMEOUT) - bfa_ioc_pf_failed(ioc); + bfa_fsm_send_event(ioc, IOC_E_FAILED); break; case IOCPF_E_DISABLE: - bfa_ioc_hw_sem_release(ioc); + writel(1, ioc->ioc_regs.ioc_sem_reg); bfa_iocpf_timer_stop(ioc); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); break; @@ -850,7 +833,7 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event) switch (event) { case IOCPF_E_FWRSP_ENABLE: bfa_iocpf_timer_stop(ioc); - bfa_ioc_hw_sem_release(ioc); + writel(1, ioc->ioc_regs.ioc_sem_reg); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_ready); break; @@ -868,16 +851,16 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event) break; } - bfa_ioc_hw_sem_release(ioc); + writel(1, ioc->ioc_regs.ioc_sem_reg); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); if (event == IOCPF_E_TIMEOUT) - bfa_ioc_pf_failed(ioc); + bfa_fsm_send_event(ioc, IOC_E_FAILED); break; case IOCPF_E_DISABLE: bfa_iocpf_timer_stop(ioc); - bfa_ioc_hw_sem_release(ioc); + writel(1, ioc->ioc_regs.ioc_sem_reg); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling); break; @@ -895,7 +878,7 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event) static void bfa_iocpf_sm_ready_entry(struct bfa_iocpf_s *iocpf) { - bfa_ioc_pf_enabled(iocpf->ioc); + bfa_fsm_send_event(iocpf->ioc, IOC_E_ENABLED); } static void @@ -919,12 +902,12 @@ bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event) break; case IOCPF_E_FWREADY: - if (bfa_ioc_is_operational(ioc)) + if (bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op)) bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); else bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); - bfa_ioc_pf_failed(ioc); + bfa_fsm_send_event(ioc, IOC_E_FAILED); break; default: @@ -982,7 +965,7 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event) static void bfa_iocpf_sm_disabled_entry(struct bfa_iocpf_s *iocpf) { - bfa_ioc_pf_disabled(iocpf->ioc); + bfa_fsm_send_event(iocpf->ioc, IOC_E_DISABLED); } static void @@ -1140,11 +1123,6 @@ bfa_ioc_sem_get(void __iomem *sem_reg) return BFA_FALSE; } -void -bfa_ioc_sem_release(void __iomem *sem_reg) -{ - writel(1, sem_reg); -} static void bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc) @@ -1164,18 +1142,6 @@ bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc) bfa_sem_timer_start(ioc); } -void -bfa_ioc_hw_sem_release(struct bfa_ioc_s *ioc) -{ - writel(1, ioc->ioc_regs.ioc_sem_reg); -} - -static void -bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc) -{ - bfa_sem_timer_stop(ioc); -} - /* * Initialize LPU local memory (aka secondary memory / SRAM) */ @@ -1255,8 +1221,8 @@ bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr) int i; u32 *fwsig = (u32 *) fwhdr; - pgnum = bfa_ioc_smem_pgnum(ioc, loff); - pgoff = bfa_ioc_smem_pgoff(ioc, loff); + pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff); + pgoff = PSS_SMEM_PGOFF(loff); writel(pgnum, ioc->ioc_regs.host_page_num_fn); for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32)); @@ -1519,13 +1485,6 @@ bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc) bfa_hb_timer_start(ioc); } -static void -bfa_ioc_hb_stop(struct bfa_ioc_s *ioc) -{ - bfa_hb_timer_stop(ioc); -} - - /* * Initiate a full firmware download. */ @@ -1547,8 +1506,8 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type, bfa_trc(ioc, bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc))); fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno); - pgnum = bfa_ioc_smem_pgnum(ioc, loff); - pgoff = bfa_ioc_smem_pgoff(ioc, loff); + pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff); + pgoff = PSS_SMEM_PGOFF(loff); writel(pgnum, ioc->ioc_regs.host_page_num_fn); @@ -1578,7 +1537,8 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type, } } - writel(bfa_ioc_smem_pgnum(ioc, 0), ioc->ioc_regs.host_page_num_fn); + writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0), + ioc->ioc_regs.host_page_num_fn); /* * Set boot type and boot param at the end. @@ -1589,11 +1549,6 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type, swab32(boot_env)); } -static void -bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force) -{ - bfa_ioc_hwinit(ioc, force); -} /* * Update BFA configuration from firmware configuration. @@ -1685,8 +1640,8 @@ bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz) int i, len; u32 *buf = tbuf; - pgnum = bfa_ioc_smem_pgnum(ioc, soff); - loff = bfa_ioc_smem_pgoff(ioc, soff); + pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, soff); + loff = PSS_SMEM_PGOFF(soff); bfa_trc(ioc, pgnum); bfa_trc(ioc, loff); bfa_trc(ioc, sz); @@ -1717,11 +1672,12 @@ bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz) writel(pgnum, ioc->ioc_regs.host_page_num_fn); } } - writel(bfa_ioc_smem_pgnum(ioc, 0), ioc->ioc_regs.host_page_num_fn); + writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0), + ioc->ioc_regs.host_page_num_fn); /* * release semaphore. */ - bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg); + writel(1, ioc->ioc_regs.ioc_init_sem_reg); bfa_trc(ioc, pgnum); return BFA_STATUS_OK; @@ -1740,8 +1696,8 @@ bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz) int i, len; u32 pgnum, loff; - pgnum = bfa_ioc_smem_pgnum(ioc, soff); - loff = bfa_ioc_smem_pgoff(ioc, soff); + pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, soff); + loff = PSS_SMEM_PGOFF(soff); bfa_trc(ioc, pgnum); bfa_trc(ioc, loff); bfa_trc(ioc, sz); @@ -1771,36 +1727,17 @@ bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz) writel(pgnum, ioc->ioc_regs.host_page_num_fn); } } - writel(bfa_ioc_smem_pgnum(ioc, 0), ioc->ioc_regs.host_page_num_fn); + writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0), + ioc->ioc_regs.host_page_num_fn); /* * release semaphore. */ - bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg); + writel(1, ioc->ioc_regs.ioc_init_sem_reg); bfa_trc(ioc, pgnum); return BFA_STATUS_OK; } -/* - * hal iocpf to ioc interface - */ -static void -bfa_ioc_pf_enabled(struct bfa_ioc_s *ioc) -{ - bfa_fsm_send_event(ioc, IOC_E_ENABLED); -} - -static void -bfa_ioc_pf_disabled(struct bfa_ioc_s *ioc) -{ - bfa_fsm_send_event(ioc, IOC_E_DISABLED); -} - -static void -bfa_ioc_pf_failed(struct bfa_ioc_s *ioc) -{ - bfa_fsm_send_event(ioc, IOC_E_FAILED); -} static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc) @@ -1831,7 +1768,7 @@ bfa_ioc_pll_init(struct bfa_ioc_s *ioc) /* * release semaphore. */ - bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg); + writel(1, ioc->ioc_regs.ioc_init_sem_reg); return BFA_STATUS_OK; } @@ -2036,15 +1973,6 @@ bfa_ioc_mem_claim(struct bfa_ioc_s *ioc, u8 *dm_kva, u64 dm_pa) ioc->attr = (struct bfi_ioc_attr_s *) dm_kva; } -/* - * Return size of dma memory required. - */ -u32 -bfa_ioc_meminfo(void) -{ - return BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ); -} - void bfa_ioc_enable(struct bfa_ioc_s *ioc) { @@ -2061,18 +1989,6 @@ bfa_ioc_disable(struct bfa_ioc_s *ioc) bfa_fsm_send_event(ioc, IOC_E_DISABLE); } -/* - * Returns memory required for saving firmware trace in case of crash. - * Driver must call this interface to allocate memory required for - * automatic saving of firmware trace. Driver should call - * bfa_ioc_debug_memclaim() right after bfa_ioc_attach() to setup this - * trace memory. - */ -int -bfa_ioc_debug_trcsz(bfa_boolean_t auto_recover) -{ - return (auto_recover) ? BFA_DBG_FWTRC_LEN : 0; -} /* * Initialize memory for saving firmware trace. Driver must initialize @@ -2082,19 +1998,7 @@ void bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave) { ioc->dbg_fwsave = dbg_fwsave; - ioc->dbg_fwsave_len = bfa_ioc_debug_trcsz(ioc->iocpf.auto_recover); -} - -u32 -bfa_ioc_smem_pgnum(struct bfa_ioc_s *ioc, u32 fmaddr) -{ - return PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, fmaddr); -} - -u32 -bfa_ioc_smem_pgoff(struct bfa_ioc_s *ioc, u32 fmaddr) -{ - return PSS_SMEM_PGOFF(fmaddr); + ioc->dbg_fwsave_len = (ioc->iocpf.auto_recover) ? BFA_DBG_FWTRC_LEN : 0; } /* @@ -2257,17 +2161,6 @@ bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc) return BFA_TRUE; } -/* - * Add to IOC heartbeat failure notification queue. To be used by common - * modules such as cee, port, diag. - */ -void -bfa_ioc_hbfail_register(struct bfa_ioc_s *ioc, - struct bfa_ioc_hbfail_notify_s *notify) -{ - list_add_tail(¬ify->qe, &ioc->hb_notify_q); -} - #define BFA_MFG_NAME "Brocade" void bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc, @@ -2299,7 +2192,7 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc, else ad_attr->prototype = 0; - ad_attr->pwwn = bfa_ioc_get_pwwn(ioc); + ad_attr->pwwn = ioc->attr->pwwn; ad_attr->mac = bfa_ioc_get_mac(ioc); ad_attr->pcie_gen = ioc_attr->pcie_gen; @@ -2448,24 +2341,6 @@ bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr) bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev); } -wwn_t -bfa_ioc_get_pwwn(struct bfa_ioc_s *ioc) -{ - return ioc->attr->pwwn; -} - -wwn_t -bfa_ioc_get_nwwn(struct bfa_ioc_s *ioc) -{ - return ioc->attr->nwwn; -} - -u64 -bfa_ioc_get_adid(struct bfa_ioc_s *ioc) -{ - return ioc->attr->mfg_pwwn; -} - mac_t bfa_ioc_get_mac(struct bfa_ioc_s *ioc) { @@ -2478,18 +2353,6 @@ bfa_ioc_get_mac(struct bfa_ioc_s *ioc) return ioc->attr->mac; } -wwn_t -bfa_ioc_get_mfg_pwwn(struct bfa_ioc_s *ioc) -{ - return ioc->attr->mfg_pwwn; -} - -wwn_t -bfa_ioc_get_mfg_nwwn(struct bfa_ioc_s *ioc) -{ - return ioc->attr->mfg_nwwn; -} - mac_t bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc) { @@ -2718,43 +2581,6 @@ bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc) /* * BFA IOC PF private functions */ - -static void -bfa_iocpf_enable(struct bfa_ioc_s *ioc) -{ - bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_ENABLE); -} - -static void -bfa_iocpf_disable(struct bfa_ioc_s *ioc) -{ - bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_DISABLE); -} - -static void -bfa_iocpf_fail(struct bfa_ioc_s *ioc) -{ - bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL); -} - -static void -bfa_iocpf_initfail(struct bfa_ioc_s *ioc) -{ - bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL); -} - -static void -bfa_iocpf_getattrfail(struct bfa_ioc_s *ioc) -{ - bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL); -} - -static void -bfa_iocpf_stop(struct bfa_ioc_s *ioc) -{ - bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP); -} - static void bfa_iocpf_timeout(void *ioc_arg) { @@ -2775,12 +2601,6 @@ bfa_iocpf_sem_timeout(void *ioc_arg) /* * bfa timer function */ -void -bfa_timer_init(struct bfa_timer_mod_s *mod) -{ - INIT_LIST_HEAD(&mod->timer_q); -} - void bfa_timer_beat(struct bfa_timer_mod_s *mod) { diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index ff012f7f0757..3c5bdd1c0c7f 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h @@ -22,6 +22,11 @@ #include "bfa_cs.h" #include "bfi.h" +#define BFA_DBG_FWTRC_ENTS (BFI_IOC_TRC_ENTS) +#define BFA_DBG_FWTRC_LEN \ + (BFA_DBG_FWTRC_ENTS * sizeof(struct bfa_trc_s) + \ + (sizeof(struct bfa_trc_mod_s) - \ + BFA_TRC_MAX * sizeof(struct bfa_trc_s))) /* * BFA timer declarations */ @@ -47,7 +52,6 @@ struct bfa_timer_mod_s { #define BFA_TIMER_FREQ 200 /* specified in millisecs */ void bfa_timer_beat(struct bfa_timer_mod_s *mod); -void bfa_timer_init(struct bfa_timer_mod_s *mod); void bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer, bfa_timer_cbfn_t timercb, void *arg, unsigned int timeout); @@ -325,7 +329,6 @@ void bfa_ioc_auto_recover(bfa_boolean_t auto_recover); void bfa_ioc_detach(struct bfa_ioc_s *ioc); void bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev, enum bfi_mclass mc); -u32 bfa_ioc_meminfo(void); void bfa_ioc_mem_claim(struct bfa_ioc_s *ioc, u8 *dm_kva, u64 dm_pa); void bfa_ioc_enable(struct bfa_ioc_s *ioc); void bfa_ioc_disable(struct bfa_ioc_s *ioc); @@ -353,7 +356,6 @@ enum bfa_ioc_state bfa_ioc_get_state(struct bfa_ioc_s *ioc); void bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr); void bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc, struct bfa_adapter_attr_s *ad_attr); -int bfa_ioc_debug_trcsz(bfa_boolean_t auto_recover); void bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave); bfa_status_t bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata, int *trclen); @@ -361,15 +363,9 @@ bfa_status_t bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata, int *trclen); bfa_status_t bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf, u32 *offset, int *buflen); -u32 bfa_ioc_smem_pgnum(struct bfa_ioc_s *ioc, u32 fmaddr); -u32 bfa_ioc_smem_pgoff(struct bfa_ioc_s *ioc, u32 fmaddr); void bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc); bfa_boolean_t bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc); -void bfa_ioc_hbfail_register(struct bfa_ioc_s *ioc, - struct bfa_ioc_hbfail_notify_s *notify); bfa_boolean_t bfa_ioc_sem_get(void __iomem *sem_reg); -void bfa_ioc_sem_release(void __iomem *sem_reg); -void bfa_ioc_hw_sem_release(struct bfa_ioc_s *ioc); void bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr); bfa_boolean_t bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, @@ -380,13 +376,8 @@ bfa_status_t bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc); /* * bfa mfg wwn API functions */ -wwn_t bfa_ioc_get_pwwn(struct bfa_ioc_s *ioc); -wwn_t bfa_ioc_get_nwwn(struct bfa_ioc_s *ioc); mac_t bfa_ioc_get_mac(struct bfa_ioc_s *ioc); -wwn_t bfa_ioc_get_mfg_pwwn(struct bfa_ioc_s *ioc); -wwn_t bfa_ioc_get_mfg_nwwn(struct bfa_ioc_s *ioc); mac_t bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc); -u64 bfa_ioc_get_adid(struct bfa_ioc_s *ioc); /* * F/W Image Size & Chunk diff --git a/drivers/scsi/bfa/bfa_ioc_cb.c b/drivers/scsi/bfa/bfa_ioc_cb.c index 61f03cbe5431..e9c8554e356e 100644 --- a/drivers/scsi/bfa/bfa_ioc_cb.c +++ b/drivers/scsi/bfa/bfa_ioc_cb.c @@ -181,7 +181,7 @@ bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc) * will lock it instead of clearing it. */ readl(ioc->ioc_regs.ioc_sem_reg); - bfa_ioc_hw_sem_release(ioc); + writel(1, ioc->ioc_regs.ioc_sem_reg); } diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c index 79fb31203636..45d0ddc88c52 100644 --- a/drivers/scsi/bfa/bfa_ioc_ct.c +++ b/drivers/scsi/bfa/bfa_ioc_ct.c @@ -83,7 +83,7 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc) */ if (usecnt == 0) { writel(1, ioc->ioc_regs.ioc_usage_reg); - bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); + writel(1, ioc->ioc_regs.ioc_usage_sem_reg); bfa_trc(ioc, usecnt); return BFA_TRUE; } @@ -101,7 +101,7 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc) */ bfa_ioc_fwver_get(ioc, &fwhdr); if (!bfa_ioc_fwver_cmp(ioc, &fwhdr)) { - bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); + writel(1, ioc->ioc_regs.ioc_usage_sem_reg); bfa_trc(ioc, usecnt); return BFA_FALSE; } @@ -111,7 +111,7 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc) */ usecnt++; writel(usecnt, ioc->ioc_regs.ioc_usage_reg); - bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); + writel(1, ioc->ioc_regs.ioc_usage_sem_reg); bfa_trc(ioc, usecnt); return BFA_TRUE; } @@ -145,7 +145,7 @@ bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc) writel(usecnt, ioc->ioc_regs.ioc_usage_reg); bfa_trc(ioc, usecnt); - bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); + writel(1, ioc->ioc_regs.ioc_usage_sem_reg); } /* @@ -313,7 +313,7 @@ bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc) if (ioc->cna) { bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); writel(0, ioc->ioc_regs.ioc_usage_reg); - bfa_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); + writel(1, ioc->ioc_regs.ioc_usage_sem_reg); } /* @@ -322,7 +322,7 @@ bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc) * will lock it instead of clearing it. */ readl(ioc->ioc_regs.ioc_sem_reg); - bfa_ioc_hw_sem_release(ioc); + writel(1, ioc->ioc_regs.ioc_sem_reg); } diff --git a/drivers/scsi/bfa/bfa_plog.h b/drivers/scsi/bfa/bfa_plog.h index bdcd8ecd4f4a..1c9baa68339b 100644 --- a/drivers/scsi/bfa/bfa_plog.h +++ b/drivers/scsi/bfa/bfa_plog.h @@ -151,6 +151,5 @@ void bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid, void bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid, enum bfa_plog_eid event, u16 misc, struct fchs_s *fchdr, u32 pld_w0); -bfa_boolean_t bfa_plog_get_setting(struct bfa_plog_s *plog); #endif /* __BFA_PORTLOG_H__ */ diff --git a/drivers/scsi/bfa/bfa_port.c b/drivers/scsi/bfa/bfa_port.c index fa57b128b3d8..76efb9a5c324 100644 --- a/drivers/scsi/bfa/bfa_port.c +++ b/drivers/scsi/bfa/bfa_port.c @@ -447,7 +447,7 @@ bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc, bfa_ioc_mbox_regisr(port->ioc, BFI_MC_PORT, bfa_port_isr, port); bfa_ioc_hbfail_init(&port->hbfail, bfa_port_hbfail, port); - bfa_ioc_hbfail_register(port->ioc, &port->hbfail); + list_add_tail(&port->hbfail.qe, &port->ioc->hb_notify_q); /* * initialize time stamp for stats reset diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c index 3a2bee4d42dd..c9192869c0fe 100644 --- a/drivers/scsi/bfa/bfa_svc.c +++ b/drivers/scsi/bfa/bfa_svc.c @@ -41,19 +41,6 @@ BFA_MODULE(uf); #define BFA_LPS_MAX_VPORTS_SUPP_CB 255 #define BFA_LPS_MAX_VPORTS_SUPP_CT 190 -/* - * lps_pvt BFA LPS private functions - */ - -enum bfa_lps_event { - BFA_LPS_SM_LOGIN = 1, /* login request from user */ - BFA_LPS_SM_LOGOUT = 2, /* logout request from user */ - BFA_LPS_SM_FWRSP = 3, /* f/w response to login/logout */ - BFA_LPS_SM_RESUME = 4, /* space present in reqq queue */ - BFA_LPS_SM_DELETE = 5, /* lps delete from user */ - BFA_LPS_SM_OFFLINE = 6, /* Link is offline */ - BFA_LPS_SM_RX_CVL = 7, /* Rx clear virtual link */ -}; /* * FC PORT related definitions @@ -113,19 +100,6 @@ enum bfa_fcport_ln_sm_event { } \ } while (0) - -enum bfa_rport_event { - BFA_RPORT_SM_CREATE = 1, /* rport create event */ - BFA_RPORT_SM_DELETE = 2, /* deleting an existing rport */ - BFA_RPORT_SM_ONLINE = 3, /* rport is online */ - BFA_RPORT_SM_OFFLINE = 4, /* rport is offline */ - BFA_RPORT_SM_FWRSP = 5, /* firmware response */ - BFA_RPORT_SM_HWFAIL = 6, /* IOC h/w failure */ - BFA_RPORT_SM_QOS_SCN = 7, /* QoS SCN from firmware */ - BFA_RPORT_SM_SET_SPEED = 8, /* Set Rport Speed */ - BFA_RPORT_SM_QRESUME = 9, /* space in requeue queue */ -}; - /* * forward declarations FCXP related functions */ @@ -438,12 +412,6 @@ bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid, } -bfa_boolean_t -bfa_plog_get_setting(struct bfa_plog_s *plog) -{ - return (bfa_boolean_t)plog->plog_enabled; -} - /* * fcxp_pvt BFA FCXP private functions */ @@ -1846,24 +1814,6 @@ bfa_lps_fdisclogo(struct bfa_lps_s *lps) bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT); } -/* - * Discard a pending login request -- should be called only for - * link down handling. - */ -void -bfa_lps_discard(struct bfa_lps_s *lps) -{ - bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE); -} - -/* - * Return lport services tag - */ -u8 -bfa_lps_get_tag(struct bfa_lps_s *lps) -{ - return lps->lp_tag; -} /* * Return lport services tag given the pid @@ -1884,55 +1834,6 @@ bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid) return 0; } -/* - * return if fabric login indicates support for NPIV - */ -bfa_boolean_t -bfa_lps_is_npiv_en(struct bfa_lps_s *lps) -{ - return lps->npiv_en; -} - -/* - * Return TRUE if attached to F-Port, else return FALSE - */ -bfa_boolean_t -bfa_lps_is_fport(struct bfa_lps_s *lps) -{ - return lps->fport; -} - -/* - * Return TRUE if attached to a Brocade Fabric - */ -bfa_boolean_t -bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps) -{ - return lps->brcd_switch; -} -/* - * return TRUE if authentication is required - */ -bfa_boolean_t -bfa_lps_is_authreq(struct bfa_lps_s *lps) -{ - return lps->auth_req; -} - -bfa_eproto_status_t -bfa_lps_get_extstatus(struct bfa_lps_s *lps) -{ - return lps->ext_status; -} - -/* - * return port id assigned to the lport - */ -u32 -bfa_lps_get_pid(struct bfa_lps_s *lps) -{ - return lps->lp_pid; -} /* * return port id assigned to the base lport @@ -1945,60 +1846,6 @@ bfa_lps_get_base_pid(struct bfa_s *bfa) return BFA_LPS_FROM_TAG(mod, 0)->lp_pid; } -/* - * Return bb_credit assigned in FLOGI response - */ -u16 -bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps) -{ - return lps->pr_bbcred; -} - -/* - * Return peer port name - */ -wwn_t -bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps) -{ - return lps->pr_pwwn; -} - -/* - * Return peer node name - */ -wwn_t -bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps) -{ - return lps->pr_nwwn; -} - -/* - * return reason code if login request is rejected - */ -u8 -bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps) -{ - return lps->lsrjt_rsn; -} - -/* - * return explanation code if login request is rejected - */ -u8 -bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps) -{ - return lps->lsrjt_expl; -} - -/* - * Return fpma/spma MAC for lport - */ -mac_t -bfa_lps_get_lp_mac(struct bfa_lps_s *lps) -{ - return lps->lp_mac; -} - /* * LPS firmware message class handler. */ @@ -3064,8 +2911,8 @@ bfa_fcport_send_disable(struct bfa_fcport_s *fcport) static void bfa_fcport_set_wwns(struct bfa_fcport_s *fcport) { - fcport->pwwn = bfa_ioc_get_pwwn(&fcport->bfa->ioc); - fcport->nwwn = bfa_ioc_get_nwwn(&fcport->bfa->ioc); + fcport->pwwn = fcport->bfa->ioc.attr->pwwn; + fcport->nwwn = fcport->bfa->ioc.attr->nwwn; bfa_trc(fcport->bfa, fcport->pwwn); bfa_trc(fcport->bfa, fcport->nwwn); @@ -3707,8 +3554,8 @@ bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr) attr->nwwn = fcport->nwwn; attr->pwwn = fcport->pwwn; - attr->factorypwwn = bfa_ioc_get_mfg_pwwn(&bfa->ioc); - attr->factorynwwn = bfa_ioc_get_mfg_nwwn(&bfa->ioc); + attr->factorypwwn = bfa->ioc.attr->mfg_pwwn; + attr->factorynwwn = bfa->ioc.attr->mfg_nwwn; memcpy(&attr->pport_cfg, &fcport->cfg, sizeof(struct bfa_port_cfg_s)); @@ -3726,7 +3573,7 @@ bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr) /* beacon attributes */ attr->beacon = fcport->beacon; attr->link_e2e_beacon = fcport->link_e2e_beacon; - attr->plog_enabled = bfa_plog_get_setting(fcport->bfa->plog); + attr->plog_enabled = (bfa_boolean_t)fcport->bfa->plog->plog_enabled; attr->io_profile = bfa_fcpim_get_io_profile(fcport->bfa); attr->pport_cfg.path_tov = bfa_fcpim_path_tov_get(bfa); @@ -4584,7 +4431,7 @@ bfa_rport_create(struct bfa_s *bfa, void *rport_drv) rp->bfa = bfa; rp->rport_drv = rport_drv; - bfa_rport_clear_stats(rp); + memset(&rp->stats, 0, sizeof(rp->stats)); bfa_assert(bfa_sm_cmp_state(rp, bfa_rport_sm_uninit)); bfa_sm_send_event(rp, BFA_RPORT_SM_CREATE); @@ -4592,12 +4439,6 @@ bfa_rport_create(struct bfa_s *bfa, void *rport_drv) return rp; } -void -bfa_rport_delete(struct bfa_rport_s *rport) -{ - bfa_sm_send_event(rport, BFA_RPORT_SM_DELETE); -} - void bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info) { @@ -4616,12 +4457,6 @@ bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info) bfa_sm_send_event(rport, BFA_RPORT_SM_ONLINE); } -void -bfa_rport_offline(struct bfa_rport_s *rport) -{ - bfa_sm_send_event(rport, BFA_RPORT_SM_OFFLINE); -} - void bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed) { @@ -4632,12 +4467,6 @@ bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed) bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED); } -void -bfa_rport_clear_stats(struct bfa_rport_s *rport) -{ - memset(&rport->stats, 0, sizeof(rport->stats)); -} - /* * SGPG related functions @@ -5101,8 +4930,6 @@ bfa_uf_start(struct bfa_s *bfa) bfa_uf_post_all(BFA_UF_MOD(bfa)); } - - /* * hal_uf_api */ diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h index 0e23c1bfcba0..29b091826e9b 100644 --- a/drivers/scsi/bfa/bfa_svc.h +++ b/drivers/scsi/bfa/bfa_svc.h @@ -220,6 +220,18 @@ void bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg); /* * RPORT related defines */ +enum bfa_rport_event { + BFA_RPORT_SM_CREATE = 1, /* rport create event */ + BFA_RPORT_SM_DELETE = 2, /* deleting an existing rport */ + BFA_RPORT_SM_ONLINE = 3, /* rport is online */ + BFA_RPORT_SM_OFFLINE = 4, /* rport is offline */ + BFA_RPORT_SM_FWRSP = 5, /* firmware response */ + BFA_RPORT_SM_HWFAIL = 6, /* IOC h/w failure */ + BFA_RPORT_SM_QOS_SCN = 7, /* QoS SCN from firmware */ + BFA_RPORT_SM_SET_SPEED = 8, /* Set Rport Speed */ + BFA_RPORT_SM_QRESUME = 9, /* space in requeue queue */ +}; + #define BFA_RPORT_MIN 4 struct bfa_rport_mod_s { @@ -516,12 +528,9 @@ bfa_boolean_t bfa_fcport_is_qos_enabled(struct bfa_s *bfa); * bfa rport API functions */ struct bfa_rport_s *bfa_rport_create(struct bfa_s *bfa, void *rport_drv); -void bfa_rport_delete(struct bfa_rport_s *rport); void bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info); -void bfa_rport_offline(struct bfa_rport_s *rport); void bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed); -void bfa_rport_clear_stats(struct bfa_rport_s *rport); void bfa_cb_rport_online(void *rport); void bfa_cb_rport_offline(void *rport); void bfa_cb_rport_qos_scn_flowid(void *rport, @@ -594,28 +603,14 @@ void bfa_uf_free(struct bfa_uf_s *uf); u32 bfa_lps_get_max_vport(struct bfa_s *bfa); struct bfa_lps_s *bfa_lps_alloc(struct bfa_s *bfa); void bfa_lps_delete(struct bfa_lps_s *lps); -void bfa_lps_discard(struct bfa_lps_s *lps); void bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz, wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en); void bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn, wwn_t nwwn); void bfa_lps_fdisclogo(struct bfa_lps_s *lps); -u8 bfa_lps_get_tag(struct bfa_lps_s *lps); -bfa_boolean_t bfa_lps_is_npiv_en(struct bfa_lps_s *lps); -bfa_boolean_t bfa_lps_is_fport(struct bfa_lps_s *lps); -bfa_boolean_t bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps); -bfa_boolean_t bfa_lps_is_authreq(struct bfa_lps_s *lps); -bfa_eproto_status_t bfa_lps_get_extstatus(struct bfa_lps_s *lps); -u32 bfa_lps_get_pid(struct bfa_lps_s *lps); u32 bfa_lps_get_base_pid(struct bfa_s *bfa); u8 bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid); -u16 bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps); -wwn_t bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps); -wwn_t bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps); -u8 bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps); -u8 bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps); -mac_t bfa_lps_get_lp_mac(struct bfa_lps_s *lps); void bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status); void bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status); void bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg); diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index 4239fdf0d2d1..2bc786212521 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -206,7 +206,7 @@ bfad_sm_created(struct bfad_s *bfad, enum bfad_sm_event event) } spin_lock_irqsave(&bfad->bfad_lock, flags); - bfa_init(&bfad->bfa); + bfa_iocfc_init(&bfad->bfa); spin_unlock_irqrestore(&bfad->bfad_lock, flags); /* Set up interrupt handler for each vectors */ @@ -725,7 +725,7 @@ bfad_bfa_tmo(unsigned long data) spin_lock_irqsave(&bfad->bfad_lock, flags); - bfa_timer_tick(&bfad->bfa); + bfa_timer_beat(&bfad->bfa.timer_mod); bfa_comp_deq(&bfad->bfa, &doneq); spin_unlock_irqrestore(&bfad->bfad_lock, flags); @@ -882,8 +882,8 @@ bfad_drv_init(struct bfad_s *bfad) goto out_hal_mem_alloc_failure; } - bfa_init_trc(&bfad->bfa, bfad->trcmod); - bfa_init_plog(&bfad->bfa, &bfad->plog_buf); + bfad->bfa.trcmod = bfad->trcmod; + bfad->bfa.plog = &bfad->plog_buf; bfa_plog_init(&bfad->plog_buf); bfa_plog_str(&bfad->plog_buf, BFA_PL_MID_DRVR, BFA_PL_EID_DRIVER_START, 0, "Driver Attach"); @@ -893,9 +893,9 @@ bfad_drv_init(struct bfad_s *bfad) /* FCS INIT */ spin_lock_irqsave(&bfad->bfad_lock, flags); - bfa_fcs_trc_init(&bfad->bfa_fcs, bfad->trcmod); + bfad->bfa_fcs.trcmod = bfad->trcmod; bfa_fcs_attach(&bfad->bfa_fcs, &bfad->bfa, bfad, BFA_FALSE); - bfa_fcs_set_fdmi_param(&bfad->bfa_fcs, fdmi_enable); + bfad->bfa_fcs.fdmi_enabled = fdmi_enable; spin_unlock_irqrestore(&bfad->bfad_lock, flags); bfad->bfad_flags |= BFAD_DRV_INIT_DONE; @@ -913,7 +913,7 @@ bfad_drv_uninit(struct bfad_s *bfad) spin_lock_irqsave(&bfad->bfad_lock, flags); init_completion(&bfad->comp); - bfa_stop(&bfad->bfa); + bfa_iocfc_stop(&bfad->bfa); spin_unlock_irqrestore(&bfad->bfad_lock, flags); wait_for_completion(&bfad->comp); @@ -932,8 +932,8 @@ bfad_drv_start(struct bfad_s *bfad) unsigned long flags; spin_lock_irqsave(&bfad->bfad_lock, flags); - bfa_start(&bfad->bfa); - bfa_fcs_start(&bfad->bfa_fcs); + bfa_iocfc_start(&bfad->bfa); + bfa_fcs_fabric_modstart(&bfad->bfa_fcs); bfad->bfad_flags |= BFAD_HAL_START_DONE; spin_unlock_irqrestore(&bfad->bfad_lock, flags); @@ -963,7 +963,7 @@ bfad_stop(struct bfad_s *bfad) spin_lock_irqsave(&bfad->bfad_lock, flags); init_completion(&bfad->comp); - bfa_stop(&bfad->bfa); + bfa_iocfc_stop(&bfad->bfa); bfad->bfad_flags &= ~BFAD_HAL_START_DONE; spin_unlock_irqrestore(&bfad->bfad_lock, flags); wait_for_completion(&bfad->comp); @@ -1524,7 +1524,7 @@ bfad_init(void) if (strcmp(FCPI_NAME, " fcpim") == 0) supported_fc4s |= BFA_LPORT_ROLE_FCP_IM; - bfa_ioc_auto_recover(ioc_auto_recover); + bfa_auto_recover = ioc_auto_recover; bfa_fcs_rport_set_del_timeout(rport_del_timeout); error = pci_register_driver(&bfad_pci_driver); diff --git a/drivers/scsi/bfa/bfad_debugfs.c b/drivers/scsi/bfa/bfad_debugfs.c index 0fbd620474c7..c66e32eced7b 100644 --- a/drivers/scsi/bfa/bfad_debugfs.c +++ b/drivers/scsi/bfa/bfad_debugfs.c @@ -90,7 +90,7 @@ bfad_debugfs_open_fwtrc(struct inode *inode, struct file *file) memset(fw_debug->debug_buffer, 0, fw_debug->buffer_len); spin_lock_irqsave(&bfad->bfad_lock, flags); - rc = bfa_debug_fwtrc(&bfad->bfa, + rc = bfa_ioc_debug_fwtrc(&bfad->bfa.ioc, fw_debug->debug_buffer, &fw_debug->buffer_len); spin_unlock_irqrestore(&bfad->bfad_lock, flags); @@ -134,7 +134,7 @@ bfad_debugfs_open_fwsave(struct inode *inode, struct file *file) memset(fw_debug->debug_buffer, 0, fw_debug->buffer_len); spin_lock_irqsave(&bfad->bfad_lock, flags); - rc = bfa_debug_fwsave(&bfad->bfa, + rc = bfa_ioc_debug_fwsave(&bfad->bfa.ioc, fw_debug->debug_buffer, &fw_debug->buffer_len); spin_unlock_irqrestore(&bfad->bfad_lock, flags); diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index fbad5e9b2402..bcab8912dd59 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c @@ -922,7 +922,7 @@ bfad_im_supported_speeds(struct bfa_s *bfa) if (!ioc_attr) return 0; - bfa_get_attr(bfa, ioc_attr); + bfa_ioc_get_attr(&bfa->ioc, ioc_attr); if (ioc_attr->adapter_attr.max_speed == BFA_PORT_SPEED_8GBPS) { if (ioc_attr->adapter_attr.is_mezz) { supported_speed |= FC_PORTSPEED_8GBIT | -- cgit v1.2.3-59-g8ed1b From b77ee1fb10e4b76dc61094b3678d805be0e4f7ba Mon Sep 17 00:00:00 2001 From: Maggie Zhang Date: Thu, 9 Dec 2010 19:09:26 -0800 Subject: [SCSI] bfa: remove a file with small size Removed bfa_drv.c, merged it to bfa_core.c and modified Makefile. Signed-off-by: Maggie Zhang Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/Makefile | 2 +- drivers/scsi/bfa/bfa.h | 1 - drivers/scsi/bfa/bfa_core.c | 87 +++++++++++++++++++++++++++++++++ drivers/scsi/bfa/bfa_drv.c | 107 ----------------------------------------- drivers/scsi/bfa/bfa_modules.h | 3 -- 5 files changed, 88 insertions(+), 112 deletions(-) delete mode 100644 drivers/scsi/bfa/bfa_drv.c diff --git a/drivers/scsi/bfa/Makefile b/drivers/scsi/bfa/Makefile index d2eefd3e3bd5..ed26a6a97a44 100644 --- a/drivers/scsi/bfa/Makefile +++ b/drivers/scsi/bfa/Makefile @@ -3,6 +3,6 @@ obj-$(CONFIG_SCSI_BFA_FC) := bfa.o bfa-y := bfad.o bfad_im.o bfad_attr.o bfad_debugfs.o bfa-y += bfa_ioc.o bfa_ioc_cb.o bfa_ioc_ct.o bfa_hw_cb.o bfa_hw_ct.o bfa-y += bfa_fcs.o bfa_fcs_lport.o bfa_fcs_rport.o bfa_fcs_fcpim.o bfa_fcbuild.o -bfa-y += bfa_port.o bfa_fcpim.o bfa_core.o bfa_drv.o bfa_svc.o +bfa-y += bfa_port.o bfa_fcpim.o bfa_core.o bfa_svc.o ccflags-y := -DBFA_PERF_BUILD diff --git a/drivers/scsi/bfa/bfa.h b/drivers/scsi/bfa/bfa.h index 6231e5aa55b3..8f17186a8dfe 100644 --- a/drivers/scsi/bfa/bfa.h +++ b/drivers/scsi/bfa/bfa.h @@ -331,7 +331,6 @@ void bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs, u32 *maxvec); void bfa_hwct_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end); -void bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi); void bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns); wwn_t bfa_iocfc_get_pwwn(struct bfa_s *bfa); wwn_t bfa_iocfc_get_nwwn(struct bfa_s *bfa); diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c index 002907c694af..d417864227ce 100644 --- a/drivers/scsi/bfa/bfa_core.c +++ b/drivers/scsi/bfa/bfa_core.c @@ -21,6 +21,93 @@ BFA_TRC_FILE(HAL, CORE); +/* + * BFA module list terminated by NULL + */ +static struct bfa_module_s *hal_mods[] = { + &hal_mod_sgpg, + &hal_mod_fcport, + &hal_mod_fcxp, + &hal_mod_lps, + &hal_mod_uf, + &hal_mod_rport, + &hal_mod_fcpim, + NULL +}; + +/* + * Message handlers for various modules. + */ +static bfa_isr_func_t bfa_isrs[BFI_MC_MAX] = { + bfa_isr_unhandled, /* NONE */ + bfa_isr_unhandled, /* BFI_MC_IOC */ + bfa_isr_unhandled, /* BFI_MC_DIAG */ + bfa_isr_unhandled, /* BFI_MC_FLASH */ + bfa_isr_unhandled, /* BFI_MC_CEE */ + bfa_fcport_isr, /* BFI_MC_FCPORT */ + bfa_isr_unhandled, /* BFI_MC_IOCFC */ + bfa_isr_unhandled, /* BFI_MC_LL */ + bfa_uf_isr, /* BFI_MC_UF */ + bfa_fcxp_isr, /* BFI_MC_FCXP */ + bfa_lps_isr, /* BFI_MC_LPS */ + bfa_rport_isr, /* BFI_MC_RPORT */ + bfa_itnim_isr, /* BFI_MC_ITNIM */ + bfa_isr_unhandled, /* BFI_MC_IOIM_READ */ + bfa_isr_unhandled, /* BFI_MC_IOIM_WRITE */ + bfa_isr_unhandled, /* BFI_MC_IOIM_IO */ + bfa_ioim_isr, /* BFI_MC_IOIM */ + bfa_ioim_good_comp_isr, /* BFI_MC_IOIM_IOCOM */ + bfa_tskim_isr, /* BFI_MC_TSKIM */ + bfa_isr_unhandled, /* BFI_MC_SBOOT */ + bfa_isr_unhandled, /* BFI_MC_IPFC */ + bfa_isr_unhandled, /* BFI_MC_PORT */ + bfa_isr_unhandled, /* --------- */ + bfa_isr_unhandled, /* --------- */ + bfa_isr_unhandled, /* --------- */ + bfa_isr_unhandled, /* --------- */ + bfa_isr_unhandled, /* --------- */ + bfa_isr_unhandled, /* --------- */ + bfa_isr_unhandled, /* --------- */ + bfa_isr_unhandled, /* --------- */ + bfa_isr_unhandled, /* --------- */ + bfa_isr_unhandled, /* --------- */ +}; +/* + * Message handlers for mailbox command classes + */ +static bfa_ioc_mbox_mcfunc_t bfa_mbox_isrs[BFI_MC_MAX] = { + NULL, + NULL, /* BFI_MC_IOC */ + NULL, /* BFI_MC_DIAG */ + NULL, /* BFI_MC_FLASH */ + NULL, /* BFI_MC_CEE */ + NULL, /* BFI_MC_PORT */ + bfa_iocfc_isr, /* BFI_MC_IOCFC */ + NULL, +}; + + + +static void +bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi) +{ + struct bfa_port_s *port = &bfa->modules.port; + u32 dm_len; + u8 *dm_kva; + u64 dm_pa; + + dm_len = bfa_port_meminfo(); + dm_kva = bfa_meminfo_dma_virt(mi); + dm_pa = bfa_meminfo_dma_phys(mi); + + memset(port, 0, sizeof(struct bfa_port_s)); + bfa_port_attach(port, &bfa->ioc, bfa, bfa->trcmod); + bfa_port_mem_claim(port, dm_kva, dm_pa); + + bfa_meminfo_dma_virt(mi) = dm_kva + dm_len; + bfa_meminfo_dma_phys(mi) = dm_pa + dm_len; +} + /* * BFA IOC FC related definitions */ diff --git a/drivers/scsi/bfa/bfa_drv.c b/drivers/scsi/bfa/bfa_drv.c deleted file mode 100644 index 0222d7c88a9a..000000000000 --- a/drivers/scsi/bfa/bfa_drv.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. - * All rights reserved - * www.brocade.com - * - * Linux driver for Brocade Fibre Channel Host Bus Adapter. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License (GPL) Version 2 as - * published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ - -#include "bfa_modules.h" - -/* - * BFA module list terminated by NULL - */ -struct bfa_module_s *hal_mods[] = { - &hal_mod_sgpg, - &hal_mod_fcport, - &hal_mod_fcxp, - &hal_mod_lps, - &hal_mod_uf, - &hal_mod_rport, - &hal_mod_fcpim, - NULL -}; - -/* - * Message handlers for various modules. - */ -bfa_isr_func_t bfa_isrs[BFI_MC_MAX] = { - bfa_isr_unhandled, /* NONE */ - bfa_isr_unhandled, /* BFI_MC_IOC */ - bfa_isr_unhandled, /* BFI_MC_DIAG */ - bfa_isr_unhandled, /* BFI_MC_FLASH */ - bfa_isr_unhandled, /* BFI_MC_CEE */ - bfa_fcport_isr, /* BFI_MC_FCPORT */ - bfa_isr_unhandled, /* BFI_MC_IOCFC */ - bfa_isr_unhandled, /* BFI_MC_LL */ - bfa_uf_isr, /* BFI_MC_UF */ - bfa_fcxp_isr, /* BFI_MC_FCXP */ - bfa_lps_isr, /* BFI_MC_LPS */ - bfa_rport_isr, /* BFI_MC_RPORT */ - bfa_itnim_isr, /* BFI_MC_ITNIM */ - bfa_isr_unhandled, /* BFI_MC_IOIM_READ */ - bfa_isr_unhandled, /* BFI_MC_IOIM_WRITE */ - bfa_isr_unhandled, /* BFI_MC_IOIM_IO */ - bfa_ioim_isr, /* BFI_MC_IOIM */ - bfa_ioim_good_comp_isr, /* BFI_MC_IOIM_IOCOM */ - bfa_tskim_isr, /* BFI_MC_TSKIM */ - bfa_isr_unhandled, /* BFI_MC_SBOOT */ - bfa_isr_unhandled, /* BFI_MC_IPFC */ - bfa_isr_unhandled, /* BFI_MC_PORT */ - bfa_isr_unhandled, /* --------- */ - bfa_isr_unhandled, /* --------- */ - bfa_isr_unhandled, /* --------- */ - bfa_isr_unhandled, /* --------- */ - bfa_isr_unhandled, /* --------- */ - bfa_isr_unhandled, /* --------- */ - bfa_isr_unhandled, /* --------- */ - bfa_isr_unhandled, /* --------- */ - bfa_isr_unhandled, /* --------- */ - bfa_isr_unhandled, /* --------- */ -}; - - -/* - * Message handlers for mailbox command classes - */ -bfa_ioc_mbox_mcfunc_t bfa_mbox_isrs[BFI_MC_MAX] = { - NULL, - NULL, /* BFI_MC_IOC */ - NULL, /* BFI_MC_DIAG */ - NULL, /* BFI_MC_FLASH */ - NULL, /* BFI_MC_CEE */ - NULL, /* BFI_MC_PORT */ - bfa_iocfc_isr, /* BFI_MC_IOCFC */ - NULL, -}; - - - -void -bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi) -{ - struct bfa_port_s *port = &bfa->modules.port; - u32 dm_len; - u8 *dm_kva; - u64 dm_pa; - - dm_len = bfa_port_meminfo(); - dm_kva = bfa_meminfo_dma_virt(mi); - dm_pa = bfa_meminfo_dma_phys(mi); - - memset(port, 0, sizeof(struct bfa_port_s)); - bfa_port_attach(port, &bfa->ioc, bfa, bfa->trcmod); - bfa_port_mem_claim(port, dm_kva, dm_pa); - - bfa_meminfo_dma_virt(mi) = dm_kva + dm_len; - bfa_meminfo_dma_phys(mi) = dm_pa + dm_len; -} diff --git a/drivers/scsi/bfa/bfa_modules.h b/drivers/scsi/bfa/bfa_modules.h index 15407ab39e77..ab79ff6fdeea 100644 --- a/drivers/scsi/bfa/bfa_modules.h +++ b/drivers/scsi/bfa/bfa_modules.h @@ -99,7 +99,6 @@ struct bfa_module_s { void (*iocdisable) (struct bfa_s *bfa); }; -extern struct bfa_module_s *hal_mods[]; struct bfa_s { void *bfad; /* BFA driver instance */ @@ -116,8 +115,6 @@ struct bfa_s { struct bfa_msix_s msix; }; -extern bfa_isr_func_t bfa_isrs[BFI_MC_MAX]; -extern bfa_ioc_mbox_mcfunc_t bfa_mbox_isrs[]; extern bfa_boolean_t bfa_auto_recover; extern struct bfa_module_s hal_mod_sgpg; extern struct bfa_module_s hal_mod_fcport; -- cgit v1.2.3-59-g8ed1b From e3e7d3eebb08735c8a14cd27f76dac784e9a9b75 Mon Sep 17 00:00:00 2001 From: Maggie Zhang Date: Thu, 9 Dec 2010 19:10:27 -0800 Subject: [SCSI] bfa: scatter gather processing change Modified scatter gather processing to use the kernel provided scsi_for_each_sg() macro. 1) Instead of allocating and setting up sgpg in bfa_ioim_sge_setup(), we only do allocation. As a result, we remove bfa_ioim_sgpg_setup() and rename bfa_ioim_sge_setup() to bfa_ioim_sgpg_alloc(). 2) bfa_ioim_send_ioreq() call scsi_for_each_sg() to handle both inline and sgpg setup. Signed-off-by: Maggie Zhang Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_fcpim.c | 140 ++++++++++++++++++------------------------- 1 file changed, 59 insertions(+), 81 deletions(-) diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c index d6aea5d4425f..c07ee42345bc 100644 --- a/drivers/scsi/bfa/bfa_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcpim.c @@ -218,8 +218,7 @@ static void bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim, * forward declaration for BFA IOIM functions */ static bfa_boolean_t bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim); -static bfa_boolean_t bfa_ioim_sge_setup(struct bfa_ioim_s *ioim); -static void bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim); +static bfa_boolean_t bfa_ioim_sgpg_alloc(struct bfa_ioim_s *ioim); static bfa_boolean_t bfa_ioim_send_abort(struct bfa_ioim_s *ioim); static void bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim); static void __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete); @@ -1621,7 +1620,7 @@ bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) } if (ioim->nsges > BFI_SGE_INLINE) { - if (!bfa_ioim_sge_setup(ioim)) { + if (!bfa_ioim_sgpg_alloc(ioim)) { bfa_sm_set_state(ioim, bfa_ioim_sm_sgalloc); return; } @@ -2304,7 +2303,7 @@ bfa_ioim_sgpg_alloced(void *cbarg) ioim->nsgpgs = BFA_SGPG_NPAGE(ioim->nsges); list_splice_tail_init(&ioim->iosp->sgpg_wqe.sgpg_q, &ioim->sgpg_q); - bfa_ioim_sgpg_setup(ioim); + ioim->sgpg = bfa_q_first(&ioim->sgpg_q); bfa_sm_send_event(ioim, BFA_IOIM_SM_SGALLOCED); } @@ -2317,12 +2316,14 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim) struct bfa_itnim_s *itnim = ioim->itnim; struct bfi_ioim_req_s *m; static struct fcp_cmnd_s cmnd_z0 = { 0 }; - struct bfi_sge_s *sge; + struct bfi_sge_s *sge, *sgpge; u32 pgdlen = 0; u32 fcp_dl; u64 addr; struct scatterlist *sg; + struct bfa_sgpg_s *sgpg; struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio; + u32 i, sge_id, pgcumsz; /* * check for room in queue to send request now @@ -2342,20 +2343,59 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim) m->rport_hdl = ioim->itnim->rport->fw_handle; m->io_timeout = bfa_cb_ioim_get_timeout(ioim->dio); - /* - * build inline IO SG element here - */ sge = &m->sges[0]; - if (ioim->nsges) { - sg = (struct scatterlist *)scsi_sglist(cmnd); - addr = bfa_os_sgaddr(sg_dma_address(sg)); - sge->sga = *(union bfi_addr_u *) &addr; - pgdlen = sg_dma_len(sg); - sge->sg_len = pgdlen; - sge->flags = (ioim->nsges > BFI_SGE_INLINE) ? + sgpg = ioim->sgpg; + sge_id = 0; + sgpge = NULL; + pgcumsz = 0; + scsi_for_each_sg(cmnd, sg, ioim->nsges, i) { + if (i == 0) { + /* build inline IO SG element */ + addr = bfa_os_sgaddr(sg_dma_address(sg)); + sge->sga = *(union bfi_addr_u *) &addr; + pgdlen = sg_dma_len(sg); + sge->sg_len = pgdlen; + sge->flags = (ioim->nsges > BFI_SGE_INLINE) ? BFI_SGE_DATA_CPL : BFI_SGE_DATA_LAST; - bfa_sge_to_be(sge); - sge++; + bfa_sge_to_be(sge); + sge++; + } else { + if (sge_id == 0) + sgpge = sgpg->sgpg->sges; + + addr = bfa_os_sgaddr(sg_dma_address(sg)); + sgpge->sga = *(union bfi_addr_u *) &addr; + sgpge->sg_len = sg_dma_len(sg); + pgcumsz += sgpge->sg_len; + + /* set flags */ + if (i < (ioim->nsges - 1) && + sge_id < (BFI_SGPG_DATA_SGES - 1)) + sgpge->flags = BFI_SGE_DATA; + else if (i < (ioim->nsges - 1)) + sgpge->flags = BFI_SGE_DATA_CPL; + else + sgpge->flags = BFI_SGE_DATA_LAST; + + bfa_sge_to_le(sgpge); + + sgpge++; + if (i == (ioim->nsges - 1)) { + sgpge->flags = BFI_SGE_PGDLEN; + sgpge->sga.a32.addr_lo = 0; + sgpge->sga.a32.addr_hi = 0; + sgpge->sg_len = pgcumsz; + bfa_sge_to_le(sgpge); + } else if (++sge_id == BFI_SGPG_DATA_SGES) { + sgpg = (struct bfa_sgpg_s *) bfa_q_next(sgpg); + sgpge->flags = BFI_SGE_LINK; + sgpge->sga = sgpg->sgpg_pa; + sgpge->sg_len = pgcumsz; + bfa_sge_to_le(sgpge); + sge_id = 0; + pgcumsz = 0; + } + } } if (ioim->nsges > BFI_SGE_INLINE) { @@ -2414,7 +2454,7 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim) * at queuing time. */ static bfa_boolean_t -bfa_ioim_sge_setup(struct bfa_ioim_s *ioim) +bfa_ioim_sgpg_alloc(struct bfa_ioim_s *ioim) { u16 nsgpgs; @@ -2434,73 +2474,11 @@ bfa_ioim_sge_setup(struct bfa_ioim_s *ioim) } ioim->nsgpgs = nsgpgs; - bfa_ioim_sgpg_setup(ioim); + ioim->sgpg = bfa_q_first(&ioim->sgpg_q); return BFA_TRUE; } -static void -bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim) -{ - int sgeid, nsges, i; - struct bfi_sge_s *sge; - struct bfa_sgpg_s *sgpg; - u32 pgcumsz; - u64 addr; - struct scatterlist *sg; - struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio; - - sgeid = BFI_SGE_INLINE; - ioim->sgpg = sgpg = bfa_q_first(&ioim->sgpg_q); - - sg = scsi_sglist(cmnd); - sg = sg_next(sg); - - do { - sge = sgpg->sgpg->sges; - nsges = ioim->nsges - sgeid; - if (nsges > BFI_SGPG_DATA_SGES) - nsges = BFI_SGPG_DATA_SGES; - - pgcumsz = 0; - for (i = 0; i < nsges; i++, sge++, sgeid++, sg = sg_next(sg)) { - addr = bfa_os_sgaddr(sg_dma_address(sg)); - sge->sga = *(union bfi_addr_u *) &addr; - sge->sg_len = sg_dma_len(sg); - pgcumsz += sge->sg_len; - - /* - * set flags - */ - if (i < (nsges - 1)) - sge->flags = BFI_SGE_DATA; - else if (sgeid < (ioim->nsges - 1)) - sge->flags = BFI_SGE_DATA_CPL; - else - sge->flags = BFI_SGE_DATA_LAST; - - bfa_sge_to_le(sge); - } - - sgpg = (struct bfa_sgpg_s *) bfa_q_next(sgpg); - - /* - * set the link element of each page - */ - if (sgeid == ioim->nsges) { - sge->flags = BFI_SGE_PGDLEN; - sge->sga.a32.addr_lo = 0; - sge->sga.a32.addr_hi = 0; - } else { - sge->flags = BFI_SGE_LINK; - sge->sga = sgpg->sgpg_pa; - } - sge->sg_len = pgcumsz; - - bfa_sge_to_le(sge); - } while (sgeid < ioim->nsges); -} - /* * Send I/O abort request to firmware. */ -- cgit v1.2.3-59-g8ed1b From f314878ab95d4802ddde066096f7b30087cea7ba Mon Sep 17 00:00:00 2001 From: Maggie Zhang Date: Thu, 9 Dec 2010 19:11:39 -0800 Subject: [SCSI] bfa: remove all SCSI IO callbacks Remove SCSI IO callbacks, and as a result remove bfa_cb_ioim.h. Signed-off-by: Maggie Zhang Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_cb_ioim.h | 169 ----------------------------------------- drivers/scsi/bfa/bfa_defs.h | 4 +- drivers/scsi/bfa/bfa_fc.h | 5 +- drivers/scsi/bfa/bfa_fcpim.c | 53 ++++++++----- drivers/scsi/bfa/bfa_fcpim.h | 8 +- drivers/scsi/bfa/bfad_im.c | 10 ++- drivers/scsi/bfa/bfi.h | 2 +- drivers/scsi/bfa/bfi_ms.h | 2 +- 8 files changed, 49 insertions(+), 204 deletions(-) delete mode 100644 drivers/scsi/bfa/bfa_cb_ioim.h diff --git a/drivers/scsi/bfa/bfa_cb_ioim.h b/drivers/scsi/bfa/bfa_cb_ioim.h deleted file mode 100644 index afb573878e20..000000000000 --- a/drivers/scsi/bfa/bfa_cb_ioim.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. - * All rights reserved - * www.brocade.com - * - * Linux driver for Brocade Fibre Channel Host Bus Adapter. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License (GPL) Version 2 as - * published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ - -#ifndef __BFA_HCB_IOIM_H__ -#define __BFA_HCB_IOIM_H__ - -#include "bfa_os_inc.h" -/* - * task attribute values in FCP-2 FCP_CMND IU - */ -#define SIMPLE_Q 0 -#define HEAD_OF_Q 1 -#define ORDERED_Q 2 -#define ACA_Q 4 -#define UNTAGGED 5 - -static inline lun_t -bfad_int_to_lun(u32 luno) -{ - union { - __be16 scsi_lun[4]; - lun_t bfa_lun; - } lun; - - lun.bfa_lun = 0; - lun.scsi_lun[0] = cpu_to_be16(luno); - - return lun.bfa_lun; -} - -/* - * Get LUN for the I/O request - */ -#define bfa_cb_ioim_get_lun(__dio) \ - bfad_int_to_lun(((struct scsi_cmnd *)__dio)->device->lun) - -/* - * Get CDB for the I/O request - */ -static inline u8 * -bfa_cb_ioim_get_cdb(struct bfad_ioim_s *dio) -{ - struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; - - return (u8 *) cmnd->cmnd; -} - -/* - * Get I/O direction (read/write) for the I/O request - */ -static inline enum fcp_iodir -bfa_cb_ioim_get_iodir(struct bfad_ioim_s *dio) -{ - struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; - enum dma_data_direction dmadir; - - dmadir = cmnd->sc_data_direction; - if (dmadir == DMA_TO_DEVICE) - return FCP_IODIR_WRITE; - else if (dmadir == DMA_FROM_DEVICE) - return FCP_IODIR_READ; - else - return FCP_IODIR_NONE; -} - -/* - * Get IO size in bytes for the I/O request - */ -static inline u32 -bfa_cb_ioim_get_size(struct bfad_ioim_s *dio) -{ - struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; - - return scsi_bufflen(cmnd); -} - -/* - * Get timeout for the I/O request - */ -static inline u8 -bfa_cb_ioim_get_timeout(struct bfad_ioim_s *dio) -{ - struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; - /* - * TBD: need a timeout for scsi passthru - */ - if (cmnd->device->host == NULL) - return 4; - - return 0; -} - -/* - * Get Command Reference Number for the I/O request. 0 if none. - */ -static inline u8 -bfa_cb_ioim_get_crn(struct bfad_ioim_s *dio) -{ - return 0; -} - -/* - * Get SAM-3 priority for the I/O request. 0 is default. - */ -static inline u8 -bfa_cb_ioim_get_priority(struct bfad_ioim_s *dio) -{ - return 0; -} - -/* - * Get task attributes for the I/O request. Default is FCP_TASK_ATTR_SIMPLE(0). - */ -static inline u8 -bfa_cb_ioim_get_taskattr(struct bfad_ioim_s *dio) -{ - struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; - u8 task_attr = UNTAGGED; - - if (cmnd->device->tagged_supported) { - switch (cmnd->tag) { - case HEAD_OF_QUEUE_TAG: - task_attr = HEAD_OF_Q; - break; - case ORDERED_QUEUE_TAG: - task_attr = ORDERED_Q; - break; - default: - task_attr = SIMPLE_Q; - break; - } - } - - return task_attr; -} - -/* - * Get CDB length in bytes for the I/O request. Default is FCP_CMND_CDB_LEN(16). - */ -static inline u8 -bfa_cb_ioim_get_cdblen(struct bfad_ioim_s *dio) -{ - struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; - - return cmnd->cmd_len; -} - -/* - * Assign queue to be used for the I/O request. This value depends on whether - * the driver wants to use the queues via any specific algorithm. Currently, - * this is not supported. - */ -#define bfa_cb_ioim_get_reqq(__dio) BFA_FALSE - -#endif /* __BFA_HCB_IOIM_H__ */ diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h index 4b5b9e35abb9..07b57c4208c1 100644 --- a/drivers/scsi/bfa/bfa_defs.h +++ b/drivers/scsi/bfa/bfa_defs.h @@ -446,8 +446,8 @@ enum bfa_boot_bootopt { * Boot lun information. */ struct bfa_boot_bootlun_s { - wwn_t pwwn; /* port wwn of target */ - lun_t lun; /* 64-bit lun */ + wwn_t pwwn; /* port wwn of target */ + struct scsi_lun lun; /* 64-bit lun */ }; #pragma pack() diff --git a/drivers/scsi/bfa/bfa_fc.h b/drivers/scsi/bfa/bfa_fc.h index ce5274a017fa..104a17f70b55 100644 --- a/drivers/scsi/bfa/bfa_fc.h +++ b/drivers/scsi/bfa/bfa_fc.h @@ -21,7 +21,6 @@ #include "bfa_os_inc.h" typedef u64 wwn_t; -typedef u64 lun_t; #define WWN_NULL (0) #define FC_SYMNAME_MAX 256 /* max name server symbolic name size */ @@ -1176,8 +1175,8 @@ struct fc_srr_s { #define FCP_CMND_LUN_LEN 8 struct fcp_cmnd_s { - lun_t lun; /* 64-bit LU number */ - u8 crn; /* command reference number */ + struct scsi_lun lun; /* 64-bit LU number */ + u8 crn; /* command reference number */ #ifdef __BIGENDIAN u8 resvd:1, priority:4, /* FCP-3: SAM-3 priority */ diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c index c07ee42345bc..455c4f4e1d3b 100644 --- a/drivers/scsi/bfa/bfa_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcpim.c @@ -16,7 +16,7 @@ */ #include "bfa_modules.h" -#include "bfa_cb_ioim.h" +#include "bfa_os_inc.h" BFA_TRC_FILE(HAL, FCPIM); BFA_MODULE(fcpim); @@ -263,7 +263,7 @@ static void bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s *ioim, static void __bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete); static void __bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete); static bfa_boolean_t bfa_tskim_match_scope(struct bfa_tskim_s *tskim, - lun_t lun); + struct scsi_lun lun); static void bfa_tskim_gather_ios(struct bfa_tskim_s *tskim); static void bfa_tskim_cleanp_comp(void *tskim_cbarg); static void bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim); @@ -2315,7 +2315,7 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim) { struct bfa_itnim_s *itnim = ioim->itnim; struct bfi_ioim_req_s *m; - static struct fcp_cmnd_s cmnd_z0 = { 0 }; + static struct fcp_cmnd_s cmnd_z0 = {{{0}}}; struct bfi_sge_s *sge, *sgpge; u32 pgdlen = 0; u32 fcp_dl; @@ -2324,6 +2324,7 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim) struct bfa_sgpg_s *sgpg; struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio; u32 i, sge_id, pgcumsz; + enum dma_data_direction dmadir; /* * check for room in queue to send request now @@ -2341,7 +2342,7 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim) */ m->io_tag = cpu_to_be16(ioim->iotag); m->rport_hdl = ioim->itnim->rport->fw_handle; - m->io_timeout = bfa_cb_ioim_get_timeout(ioim->dio); + m->io_timeout = 0; sge = &m->sges[0]; sgpg = ioim->sgpg; @@ -2412,10 +2413,17 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim) * set up I/O command parameters */ m->cmnd = cmnd_z0; - m->cmnd.lun = bfa_cb_ioim_get_lun(ioim->dio); - m->cmnd.iodir = bfa_cb_ioim_get_iodir(ioim->dio); - m->cmnd.cdb = *(scsi_cdb_t *)bfa_cb_ioim_get_cdb(ioim->dio); - fcp_dl = bfa_cb_ioim_get_size(ioim->dio); + int_to_scsilun(cmnd->device->lun, &m->cmnd.lun); + dmadir = cmnd->sc_data_direction; + if (dmadir == DMA_TO_DEVICE) + m->cmnd.iodir = FCP_IODIR_WRITE; + else if (dmadir == DMA_FROM_DEVICE) + m->cmnd.iodir = FCP_IODIR_READ; + else + m->cmnd.iodir = FCP_IODIR_NONE; + + m->cmnd.cdb = *(scsi_cdb_t *) cmnd->cmnd; + fcp_dl = scsi_bufflen(cmnd); m->cmnd.fcp_dl = cpu_to_be32(fcp_dl); /* @@ -2439,7 +2447,7 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim) bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa)); } if (itnim->seq_rec || - (bfa_cb_ioim_get_size(ioim->dio) & (sizeof(u32) - 1))) + (scsi_bufflen(cmnd) & (sizeof(u32) - 1))) bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa)); /* @@ -2769,7 +2777,8 @@ bfa_ioim_profile_start(struct bfa_ioim_s *ioim) void bfa_ioim_profile_comp(struct bfa_ioim_s *ioim) { - u32 fcp_dl = bfa_cb_ioim_get_size(ioim->dio); + struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio; + u32 fcp_dl = scsi_bufflen(cmnd); u32 index = bfa_ioim_get_index(fcp_dl); u64 end_time = jiffies; struct bfa_itnim_latency_s *io_lat = @@ -2895,8 +2904,7 @@ bfa_ioim_start(struct bfa_ioim_s *ioim) * Obtain the queue over which this request has to be issued */ ioim->reqq = bfa_fcpim_ioredirect_enabled(ioim->bfa) ? - bfa_cb_ioim_get_reqq(ioim->dio) : - bfa_itnim_get_reqq(ioim); + BFA_FALSE : bfa_itnim_get_reqq(ioim); bfa_sm_send_event(ioim, BFA_IOIM_SM_START); } @@ -3186,7 +3194,7 @@ __bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete) } static bfa_boolean_t -bfa_tskim_match_scope(struct bfa_tskim_s *tskim, lun_t lun) +bfa_tskim_match_scope(struct bfa_tskim_s *tskim, struct scsi_lun lun) { switch (tskim->tm_cmnd) { case FCP_TM_TARGET_RESET: @@ -3196,7 +3204,7 @@ bfa_tskim_match_scope(struct bfa_tskim_s *tskim, lun_t lun) case FCP_TM_CLEAR_TASK_SET: case FCP_TM_LUN_RESET: case FCP_TM_CLEAR_ACA: - return (tskim->lun == lun); + return (!memcmp(&tskim->lun, &lun, sizeof(lun))); default: bfa_assert(0); @@ -3213,7 +3221,9 @@ bfa_tskim_gather_ios(struct bfa_tskim_s *tskim) { struct bfa_itnim_s *itnim = tskim->itnim; struct bfa_ioim_s *ioim; - struct list_head *qe, *qen; + struct list_head *qe, *qen; + struct scsi_cmnd *cmnd; + struct scsi_lun scsilun; INIT_LIST_HEAD(&tskim->io_q); @@ -3222,8 +3232,9 @@ bfa_tskim_gather_ios(struct bfa_tskim_s *tskim) */ list_for_each_safe(qe, qen, &itnim->io_q) { ioim = (struct bfa_ioim_s *) qe; - if (bfa_tskim_match_scope - (tskim, bfa_cb_ioim_get_lun(ioim->dio))) { + cmnd = (struct scsi_cmnd *) ioim->dio; + int_to_scsilun(cmnd->device->lun, &scsilun); + if (bfa_tskim_match_scope(tskim, scsilun)) { list_del(&ioim->qe); list_add_tail(&ioim->qe, &tskim->io_q); } @@ -3234,8 +3245,9 @@ bfa_tskim_gather_ios(struct bfa_tskim_s *tskim) */ list_for_each_safe(qe, qen, &itnim->pending_q) { ioim = (struct bfa_ioim_s *) qe; - if (bfa_tskim_match_scope - (tskim, bfa_cb_ioim_get_lun(ioim->dio))) { + cmnd = (struct scsi_cmnd *) ioim->dio; + int_to_scsilun(cmnd->device->lun, &scsilun); + if (bfa_tskim_match_scope(tskim, scsilun)) { list_del(&ioim->qe); list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q); bfa_ioim_tov(ioim); @@ -3494,7 +3506,8 @@ bfa_tskim_free(struct bfa_tskim_s *tskim) * @return None. */ void -bfa_tskim_start(struct bfa_tskim_s *tskim, struct bfa_itnim_s *itnim, lun_t lun, +bfa_tskim_start(struct bfa_tskim_s *tskim, struct bfa_itnim_s *itnim, + struct scsi_lun lun, enum fcp_tm_cmnd tm_cmnd, u8 tsecs) { tskim->itnim = itnim; diff --git a/drivers/scsi/bfa/bfa_fcpim.h b/drivers/scsi/bfa/bfa_fcpim.h index 18bdc44432ac..7d0eababa5df 100644 --- a/drivers/scsi/bfa/bfa_fcpim.h +++ b/drivers/scsi/bfa/bfa_fcpim.h @@ -146,9 +146,9 @@ struct bfa_tskim_s { struct bfa_s *bfa; /* BFA module */ struct bfa_fcpim_mod_s *fcpim; /* parent fcpim module */ struct bfa_itnim_s *itnim; /* i-t-n nexus for this IO */ - struct bfad_tskim_s *dtsk; /* driver task mgmt cmnd */ - bfa_boolean_t notify; /* notify itnim on TM comp */ - lun_t lun; /* lun if applicable */ + struct bfad_tskim_s *dtsk; /* driver task mgmt cmnd */ + bfa_boolean_t notify; /* notify itnim on TM comp */ + struct scsi_lun lun; /* lun if applicable */ enum fcp_tm_cmnd tm_cmnd; /* task management command */ u16 tsk_tag; /* FWI IO tag */ u8 tsecs; /* timeout in seconds */ @@ -389,7 +389,7 @@ struct bfa_tskim_s *bfa_tskim_alloc(struct bfa_s *bfa, struct bfad_tskim_s *dtsk); void bfa_tskim_free(struct bfa_tskim_s *tskim); void bfa_tskim_start(struct bfa_tskim_s *tskim, - struct bfa_itnim_s *itnim, lun_t lun, + struct bfa_itnim_s *itnim, struct scsi_lun lun, enum fcp_tm_cmnd tm, u8 t_secs); void bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk, enum bfi_tskim_status tsk_status); diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index bcab8912dd59..d10adcbf24b3 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c @@ -21,7 +21,6 @@ #include "bfad_drv.h" #include "bfad_im.h" -#include "bfa_cb_ioim.h" #include "bfa_fcs.h" BFA_TRC_FILE(LDRV, IM); @@ -258,6 +257,7 @@ bfad_im_target_reset_send(struct bfad_s *bfad, struct scsi_cmnd *cmnd, struct bfa_tskim_s *tskim; struct bfa_itnim_s *bfa_itnim; bfa_status_t rc = BFA_STATUS_OK; + struct scsi_lun scsilun; tskim = bfa_tskim_alloc(&bfad->bfa, (struct bfad_tskim_s *) cmnd); if (!tskim) { @@ -274,7 +274,8 @@ bfad_im_target_reset_send(struct bfad_s *bfad, struct scsi_cmnd *cmnd, cmnd->host_scribble = NULL; cmnd->SCp.Status = 0; bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim->fcs_itnim); - bfa_tskim_start(tskim, bfa_itnim, (lun_t)0, + memset(&scsilun, 0, sizeof(scsilun)); + bfa_tskim_start(tskim, bfa_itnim, scsilun, FCP_TM_TARGET_RESET, BFAD_TARGET_RESET_TMO); out: return rc; @@ -301,6 +302,7 @@ bfad_im_reset_lun_handler(struct scsi_cmnd *cmnd) int rc = SUCCESS; unsigned long flags; enum bfi_tskim_status task_status; + struct scsi_lun scsilun; spin_lock_irqsave(&bfad->bfad_lock, flags); itnim = itnim_data->itnim; @@ -327,8 +329,8 @@ bfad_im_reset_lun_handler(struct scsi_cmnd *cmnd) cmnd->SCp.ptr = (char *)&wq; cmnd->SCp.Status = 0; bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim->fcs_itnim); - bfa_tskim_start(tskim, bfa_itnim, - bfad_int_to_lun(cmnd->device->lun), + int_to_scsilun(cmnd->device->lun, &scsilun); + bfa_tskim_start(tskim, bfa_itnim, scsilun, FCP_TM_LUN_RESET, BFAD_LUN_RESET_TMO); spin_unlock_irqrestore(&bfad->bfad_lock, flags); diff --git a/drivers/scsi/bfa/bfi.h b/drivers/scsi/bfa/bfi.h index 27b33c765ddc..e19448427042 100644 --- a/drivers/scsi/bfa/bfi.h +++ b/drivers/scsi/bfa/bfi.h @@ -399,7 +399,7 @@ union bfi_ioc_i2h_msg_u { */ struct bfi_pbc_blun_s { wwn_t tgt_pwwn; - lun_t tgt_lun; + struct scsi_lun tgt_lun; }; /* diff --git a/drivers/scsi/bfa/bfi_ms.h b/drivers/scsi/bfa/bfi_ms.h index 10288764439d..e0e5318ce007 100644 --- a/drivers/scsi/bfa/bfi_ms.h +++ b/drivers/scsi/bfa/bfi_ms.h @@ -725,7 +725,7 @@ struct bfi_tskim_req_s { struct bfi_mhdr_s mh; /* Common msg header */ __be16 tsk_tag; /* task management tag */ u16 itn_fhdl; /* itn firmware handle */ - lun_t lun; /* LU number */ + struct scsi_lun lun; /* LU number */ u8 tm_flags; /* see enum fcp_tm_cmnd */ u8 t_secs; /* Timeout value in seconds */ u8 rsvd[2]; -- cgit v1.2.3-59-g8ed1b From f16a17507b09e10e0cccc4d675ccbfe030d51ef1 Mon Sep 17 00:00:00 2001 From: Maggie Zhang Date: Thu, 9 Dec 2010 19:12:32 -0800 Subject: [SCSI] bfa: remove all OS wrappers Remove OS wrapper functions/macros, and as a result remove bfa_os_inc.h. Signed-off-by: Maggie Zhang Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa.h | 2 +- drivers/scsi/bfa/bfa_core.c | 2 +- drivers/scsi/bfa/bfa_cs.h | 51 +++++++++++++- drivers/scsi/bfa/bfa_defs.h | 2 +- drivers/scsi/bfa/bfa_fc.h | 24 +++---- drivers/scsi/bfa/bfa_fcbuild.c | 58 ++++++++-------- drivers/scsi/bfa/bfa_fcbuild.h | 2 +- drivers/scsi/bfa/bfa_fcpim.c | 24 +------ drivers/scsi/bfa/bfa_fcs.c | 8 +-- drivers/scsi/bfa/bfa_fcs.h | 2 +- drivers/scsi/bfa/bfa_fcs_fcpim.c | 2 +- drivers/scsi/bfa/bfa_fcs_lport.c | 12 ++-- drivers/scsi/bfa/bfa_fcs_rport.c | 2 +- drivers/scsi/bfa/bfa_hw_cb.c | 1 + drivers/scsi/bfa/bfa_hw_ct.c | 1 + drivers/scsi/bfa/bfa_ioc.c | 6 +- drivers/scsi/bfa/bfa_ioc.h | 8 +-- drivers/scsi/bfa/bfa_ioc_cb.c | 1 + drivers/scsi/bfa/bfa_ioc_ct.c | 1 + drivers/scsi/bfa/bfa_os_inc.h | 143 --------------------------------------- drivers/scsi/bfa/bfa_port.c | 15 ++-- drivers/scsi/bfa/bfa_svc.c | 35 ++++++---- drivers/scsi/bfa/bfad.c | 9 ++- drivers/scsi/bfa/bfad_attr.c | 10 +-- drivers/scsi/bfa/bfad_drv.h | 37 ++++++---- drivers/scsi/bfa/bfad_im.c | 38 +++++------ drivers/scsi/bfa/bfad_im.h | 16 ++--- drivers/scsi/bfa/bfi.h | 2 +- 28 files changed, 210 insertions(+), 304 deletions(-) delete mode 100644 drivers/scsi/bfa/bfa_os_inc.h diff --git a/drivers/scsi/bfa/bfa.h b/drivers/scsi/bfa/bfa.h index 8f17186a8dfe..cabc6b92b25d 100644 --- a/drivers/scsi/bfa/bfa.h +++ b/drivers/scsi/bfa/bfa.h @@ -17,7 +17,7 @@ #ifndef __BFA_H__ #define __BFA_H__ -#include "bfa_os_inc.h" +#include "bfad_drv.h" #include "bfa_cs.h" #include "bfa_plog.h" #include "bfa_defs_svc.h" diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c index d417864227ce..02a5e04e365f 100644 --- a/drivers/scsi/bfa/bfa_core.c +++ b/drivers/scsi/bfa/bfa_core.c @@ -15,9 +15,9 @@ * General Public License for more details. */ +#include "bfad_drv.h" #include "bfa_modules.h" #include "bfi_ctreg.h" -#include "bfad_drv.h" BFA_TRC_FILE(HAL, CORE); diff --git a/drivers/scsi/bfa/bfa_cs.h b/drivers/scsi/bfa/bfa_cs.h index 99f242b9aa31..493009d880a8 100644 --- a/drivers/scsi/bfa/bfa_cs.h +++ b/drivers/scsi/bfa/bfa_cs.h @@ -22,7 +22,7 @@ #ifndef __BFA_CS_H__ #define __BFA_CS_H__ -#include "bfa_os_inc.h" +#include "bfad_drv.h" /* * BFA TRC @@ -32,12 +32,20 @@ #define BFA_TRC_MAX (4 * 1024) #endif +#define BFA_TRC_TS(_trcm) \ + ({ \ + struct timeval tv; \ + \ + do_gettimeofday(&tv); \ + (tv.tv_sec*1000000+tv.tv_usec); \ + }) + #ifndef BFA_TRC_TS #define BFA_TRC_TS(_trcm) ((_trcm)->ticks++) #endif struct bfa_trc_s { -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN u16 fileno; u16 line; #else @@ -361,4 +369,43 @@ bfa_wc_wait(struct bfa_wc_s *wc) bfa_wc_down(wc); } +static inline void +wwn2str(char *wwn_str, u64 wwn) +{ + union { + u64 wwn; + u8 byte[8]; + } w; + + w.wwn = wwn; + sprintf(wwn_str, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", w.byte[0], + w.byte[1], w.byte[2], w.byte[3], w.byte[4], w.byte[5], + w.byte[6], w.byte[7]); +} + +static inline void +fcid2str(char *fcid_str, u32 fcid) +{ + union { + u32 fcid; + u8 byte[4]; + } f; + + f.fcid = fcid; + sprintf(fcid_str, "%02x:%02x:%02x", f.byte[1], f.byte[2], f.byte[3]); +} + +#define bfa_swap_3b(_x) \ + ((((_x) & 0xff) << 16) | \ + ((_x) & 0x00ff00) | \ + (((_x) & 0xff0000) >> 16)) + +#ifndef __BIG_ENDIAN +#define bfa_hton3b(_x) bfa_swap_3b(_x) +#else +#define bfa_hton3b(_x) (_x) +#endif + +#define bfa_ntoh3b(_x) bfa_hton3b(_x) + #endif /* __BFA_CS_H__ */ diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h index 07b57c4208c1..d85f93aea465 100644 --- a/drivers/scsi/bfa/bfa_defs.h +++ b/drivers/scsi/bfa/bfa_defs.h @@ -19,7 +19,7 @@ #define __BFA_DEFS_H__ #include "bfa_fc.h" -#include "bfa_os_inc.h" +#include "bfad_drv.h" #define BFA_MFG_SERIALNUM_SIZE 11 #define STRSZ(_n) (((_n) + 4) & ~3) diff --git a/drivers/scsi/bfa/bfa_fc.h b/drivers/scsi/bfa/bfa_fc.h index 104a17f70b55..0d04ba9574f9 100644 --- a/drivers/scsi/bfa/bfa_fc.h +++ b/drivers/scsi/bfa/bfa_fc.h @@ -18,7 +18,7 @@ #ifndef __BFA_FC_H__ #define __BFA_FC_H__ -#include "bfa_os_inc.h" +#include "bfad_drv.h" typedef u64 wwn_t; @@ -62,7 +62,7 @@ struct scsi_cdb_s { * Fibre Channel Header Structure (FCHS) definition */ struct fchs_s { -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN u32 routing:4; /* routing bits */ u32 cat_info:4; /* category info */ #else @@ -317,7 +317,7 @@ struct fc_plogi_csp_s { u8 verlo; /* FC-PH low version */ __be16 bbcred; /* BB_Credit */ -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN u8 ciro:1, /* continuously increasing RO */ rro:1, /* random relative offset */ npiv_supp:1, /* NPIV supported */ @@ -367,7 +367,7 @@ struct fc_plogi_csp_s { * FC-PH-x. Figure 78. pg. 318. */ struct fc_plogi_clp_s { -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN u32 class_valid:1; u32 intermix:1; /* class intermix supported if set =1. * valid only for class1. Reserved for @@ -532,7 +532,7 @@ struct fc_rsi_s { */ struct fc_prli_params_s { u32 reserved:16; -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN u32 reserved1:5; u32 rec_support:1; u32 task_retry_id:1; @@ -574,7 +574,7 @@ enum { struct fc_prli_params_page_s { u32 type:8; u32 codext:8; -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN u32 origprocasv:1; u32 rsppav:1; u32 imagepair:1; @@ -610,7 +610,7 @@ struct fc_prli_s { struct fc_prlo_params_page_s { u32 type:8; u32 type_ext:8; -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN u32 opa_valid:1; /* originator process associator * valid */ @@ -646,7 +646,7 @@ struct fc_prlo_acc_params_page_s { u32 type:8; u32 type_ext:8; -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN u32 opa_valid:1; /* originator process associator * valid */ @@ -803,7 +803,7 @@ struct fc_tprlo_params_page_s { u32 type:8; u32 type_ext:8; -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN u32 opa_valid:1; u32 rpa_valid:1; u32 tpo_nport_valid:1; @@ -1177,7 +1177,7 @@ struct fc_srr_s { struct fcp_cmnd_s { struct scsi_lun lun; /* 64-bit LU number */ u8 crn; /* command reference number */ -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN u8 resvd:1, priority:4, /* FCP-3: SAM-3 priority */ taskattr:3; /* scsi task attribute */ @@ -1187,7 +1187,7 @@ struct fcp_cmnd_s { resvd:1; #endif u8 tm_flags; /* task management flags */ -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN u8 addl_cdb_len:6, /* additional CDB length words */ iodir:2; /* read/write FCP_DATA IUs */ #else @@ -1273,7 +1273,7 @@ struct fcp_rspinfo_s { struct fcp_resp_s { u32 reserved[2]; /* 2 words reserved */ u16 reserved2; -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN u8 reserved3:3; u8 fcp_conf_req:1; /* FCP_CONF is requested */ u8 resid_flags:2; /* underflow/overflow */ diff --git a/drivers/scsi/bfa/bfa_fcbuild.c b/drivers/scsi/bfa/bfa_fcbuild.c index 322b11e10d67..1ca5af75dd37 100644 --- a/drivers/scsi/bfa/bfa_fcbuild.c +++ b/drivers/scsi/bfa/bfa_fcbuild.c @@ -18,7 +18,7 @@ * fcbuild.c - FC link service frame building and parsing routines */ -#include "bfa_os_inc.h" +#include "bfad_drv.h" #include "bfa_fcbuild.h" /* @@ -48,7 +48,7 @@ fcbuild_init(void) fc_els_req_tmpl.cat_info = FC_CAT_LD_REQUEST; fc_els_req_tmpl.type = FC_TYPE_ELS; fc_els_req_tmpl.f_ctl = - bfa_os_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ | + bfa_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ | FCTL_SI_XFER); fc_els_req_tmpl.rx_id = FC_RXID_ANY; @@ -59,7 +59,7 @@ fcbuild_init(void) fc_els_rsp_tmpl.cat_info = FC_CAT_LD_REPLY; fc_els_rsp_tmpl.type = FC_TYPE_ELS; fc_els_rsp_tmpl.f_ctl = - bfa_os_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH | + bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH | FCTL_END_SEQ | FCTL_SI_XFER); fc_els_rsp_tmpl.rx_id = FC_RXID_ANY; @@ -68,7 +68,7 @@ fcbuild_init(void) */ fc_bls_req_tmpl.routing = FC_RTG_BASIC_LINK; fc_bls_req_tmpl.type = FC_TYPE_BLS; - fc_bls_req_tmpl.f_ctl = bfa_os_hton3b(FCTL_END_SEQ | FCTL_SI_XFER); + fc_bls_req_tmpl.f_ctl = bfa_hton3b(FCTL_END_SEQ | FCTL_SI_XFER); fc_bls_req_tmpl.rx_id = FC_RXID_ANY; /* @@ -78,7 +78,7 @@ fcbuild_init(void) fc_bls_rsp_tmpl.cat_info = FC_CAT_BA_ACC; fc_bls_rsp_tmpl.type = FC_TYPE_BLS; fc_bls_rsp_tmpl.f_ctl = - bfa_os_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH | + bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH | FCTL_END_SEQ | FCTL_SI_XFER); fc_bls_rsp_tmpl.rx_id = FC_RXID_ANY; @@ -129,7 +129,7 @@ fcbuild_init(void) fcp_fchs_tmpl.cat_info = FC_CAT_UNSOLICIT_CMD; fcp_fchs_tmpl.type = FC_TYPE_FCP; fcp_fchs_tmpl.f_ctl = - bfa_os_hton3b(FCTL_FS_EXCH | FCTL_END_SEQ | FCTL_SI_XFER); + bfa_hton3b(FCTL_FS_EXCH | FCTL_END_SEQ | FCTL_SI_XFER); fcp_fchs_tmpl.seq_id = 1; fcp_fchs_tmpl.rx_id = FC_RXID_ANY; } @@ -143,7 +143,7 @@ fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u32 ox_id) fchs->cat_info = FC_CAT_UNSOLICIT_CTRL; fchs->type = FC_TYPE_SERVICES; fchs->f_ctl = - bfa_os_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ | + bfa_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ | FCTL_SI_XFER); fchs->rx_id = FC_RXID_ANY; fchs->d_id = (d_id); @@ -232,7 +232,7 @@ fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id, u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size, u8 set_npiv, u8 set_auth, u16 local_bb_credits) { - u32 d_id = bfa_os_hton3b(FC_FABRIC_PORT); + u32 d_id = bfa_hton3b(FC_FABRIC_PORT); __be32 *vvl_info; memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s)); @@ -289,7 +289,7 @@ u16 fc_fdisc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id, u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size) { - u32 d_id = bfa_os_hton3b(FC_FABRIC_PORT); + u32 d_id = bfa_hton3b(FC_FABRIC_PORT); memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s)); @@ -770,10 +770,10 @@ u16 fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2, u32 d_id, u32 s_id, u32 *pid_list, u16 npids) { - u32 dctlr_id = FC_DOMAIN_CTRLR(bfa_os_hton3b(d_id)); + u32 dctlr_id = FC_DOMAIN_CTRLR(bfa_hton3b(d_id)); int i = 0; - fc_els_req_build(fchs, bfa_os_hton3b(dctlr_id), s_id, 0); + fc_els_req_build(fchs, bfa_hton3b(dctlr_id), s_id, 0); memset(rpsc2, 0, sizeof(struct fc_rpsc2_cmd_s)); @@ -1045,7 +1045,7 @@ fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, { struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; struct fcgs_gidpn_req_s *gidpn = (struct fcgs_gidpn_req_s *)(cthdr + 1); - u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); + u32 d_id = bfa_hton3b(FC_NAME_SERVER); fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); fc_gs_cthdr_build(cthdr, s_id, GS_GID_PN); @@ -1061,7 +1061,7 @@ fc_gpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, { struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; fcgs_gpnid_req_t *gpnid = (fcgs_gpnid_req_t *) (cthdr + 1); - u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); + u32 d_id = bfa_hton3b(FC_NAME_SERVER); fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); fc_gs_cthdr_build(cthdr, s_id, GS_GPN_ID); @@ -1077,7 +1077,7 @@ fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, { struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; fcgs_gnnid_req_t *gnnid = (fcgs_gnnid_req_t *) (cthdr + 1); - u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); + u32 d_id = bfa_hton3b(FC_NAME_SERVER); fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); fc_gs_cthdr_build(cthdr, s_id, GS_GNN_ID); @@ -1104,7 +1104,7 @@ u16 fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr, u8 set_br_reg, u32 s_id, u16 ox_id) { - u32 d_id = bfa_os_hton3b(FC_FABRIC_CONTROLLER); + u32 d_id = bfa_hton3b(FC_FABRIC_CONTROLLER); fc_els_req_build(fchs, d_id, s_id, ox_id); @@ -1121,7 +1121,7 @@ u16 fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn, u32 s_id, u16 ox_id) { - u32 d_id = bfa_os_hton3b(FC_FABRIC_CONTROLLER); + u32 d_id = bfa_hton3b(FC_FABRIC_CONTROLLER); u16 payldlen; fc_els_req_build(fchs, d_id, s_id, ox_id); @@ -1143,7 +1143,7 @@ fc_rftid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, { struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1); - u32 type_value, d_id = bfa_os_hton3b(FC_NAME_SERVER); + u32 type_value, d_id = bfa_hton3b(FC_NAME_SERVER); u8 index; fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); @@ -1167,7 +1167,7 @@ fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, { struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1); - u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); + u32 d_id = bfa_hton3b(FC_NAME_SERVER); fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID); @@ -1187,7 +1187,7 @@ fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, { struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; struct fcgs_rffid_req_s *rffid = (struct fcgs_rffid_req_s *)(cthdr + 1); - u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); + u32 d_id = bfa_hton3b(FC_NAME_SERVER); fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); fc_gs_cthdr_build(cthdr, s_id, GS_RFF_ID); @@ -1209,7 +1209,7 @@ fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; struct fcgs_rspnid_req_s *rspnid = (struct fcgs_rspnid_req_s *)(cthdr + 1); - u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); + u32 d_id = bfa_hton3b(FC_NAME_SERVER); fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); fc_gs_cthdr_build(cthdr, s_id, GS_RSPN_ID); @@ -1229,7 +1229,7 @@ fc_gid_ft_build(struct fchs_s *fchs, void *pyld, u32 s_id, u8 fc4_type) struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; struct fcgs_gidft_req_s *gidft = (struct fcgs_gidft_req_s *)(cthdr + 1); - u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); + u32 d_id = bfa_hton3b(FC_NAME_SERVER); fc_gs_fchdr_build(fchs, d_id, s_id, 0); @@ -1249,7 +1249,7 @@ fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id, { struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; struct fcgs_rpnid_req_s *rpnid = (struct fcgs_rpnid_req_s *)(cthdr + 1); - u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); + u32 d_id = bfa_hton3b(FC_NAME_SERVER); fc_gs_fchdr_build(fchs, d_id, s_id, 0); fc_gs_cthdr_build(cthdr, s_id, GS_RPN_ID); @@ -1267,7 +1267,7 @@ fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id, { struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; struct fcgs_rnnid_req_s *rnnid = (struct fcgs_rnnid_req_s *)(cthdr + 1); - u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); + u32 d_id = bfa_hton3b(FC_NAME_SERVER); fc_gs_fchdr_build(fchs, d_id, s_id, 0); fc_gs_cthdr_build(cthdr, s_id, GS_RNN_ID); @@ -1286,7 +1286,7 @@ fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id, struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; struct fcgs_rcsid_req_s *rcsid = (struct fcgs_rcsid_req_s *) (cthdr + 1); - u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); + u32 d_id = bfa_hton3b(FC_NAME_SERVER); fc_gs_fchdr_build(fchs, d_id, s_id, 0); fc_gs_cthdr_build(cthdr, s_id, GS_RCS_ID); @@ -1304,7 +1304,7 @@ fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id, { struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; struct fcgs_rptid_req_s *rptid = (struct fcgs_rptid_req_s *)(cthdr + 1); - u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); + u32 d_id = bfa_hton3b(FC_NAME_SERVER); fc_gs_fchdr_build(fchs, d_id, s_id, 0); fc_gs_cthdr_build(cthdr, s_id, GS_RPT_ID); @@ -1321,7 +1321,7 @@ fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id) { struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; struct fcgs_ganxt_req_s *ganxt = (struct fcgs_ganxt_req_s *)(cthdr + 1); - u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); + u32 d_id = bfa_hton3b(FC_NAME_SERVER); fc_gs_fchdr_build(fchs, d_id, s_id, 0); fc_gs_cthdr_build(cthdr, s_id, GS_GA_NXT); @@ -1341,7 +1341,7 @@ fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id, { struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; - u32 d_id = bfa_os_hton3b(FC_MGMT_SERVER); + u32 d_id = bfa_hton3b(FC_MGMT_SERVER); fc_gs_fchdr_build(fchs, d_id, s_id, 0); fc_gs_fdmi_cthdr_build(cthdr, s_id, cmd_code); @@ -1377,7 +1377,7 @@ fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn) { struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; fcgs_gmal_req_t *gmal = (fcgs_gmal_req_t *) (cthdr + 1); - u32 d_id = bfa_os_hton3b(FC_MGMT_SERVER); + u32 d_id = bfa_hton3b(FC_MGMT_SERVER); fc_gs_fchdr_build(fchs, d_id, s_id, 0); fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GMAL_CMD, @@ -1397,7 +1397,7 @@ fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn) { struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; fcgs_gfn_req_t *gfn = (fcgs_gfn_req_t *) (cthdr + 1); - u32 d_id = bfa_os_hton3b(FC_MGMT_SERVER); + u32 d_id = bfa_hton3b(FC_MGMT_SERVER); fc_gs_fchdr_build(fchs, d_id, s_id, 0); fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GFN_CMD, diff --git a/drivers/scsi/bfa/bfa_fcbuild.h b/drivers/scsi/bfa/bfa_fcbuild.h index 1737e08e1c01..ece51ec7620b 100644 --- a/drivers/scsi/bfa/bfa_fcbuild.h +++ b/drivers/scsi/bfa/bfa_fcbuild.h @@ -21,7 +21,7 @@ #ifndef __FCBUILD_H__ #define __FCBUILD_H__ -#include "bfa_os_inc.h" +#include "bfad_drv.h" #include "bfa_fc.h" #include "bfa_defs_fcs.h" diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c index 455c4f4e1d3b..506f1d326e5b 100644 --- a/drivers/scsi/bfa/bfa_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcpim.c @@ -15,8 +15,8 @@ * General Public License for more details. */ +#include "bfad_drv.h" #include "bfa_modules.h" -#include "bfa_os_inc.h" BFA_TRC_FILE(HAL, FCPIM); BFA_MODULE(fcpim); @@ -1560,24 +1560,6 @@ bfa_itnim_hold_io(struct bfa_itnim_s *itnim) bfa_sm_cmp_state(itnim, bfa_itnim_sm_iocdisable)); } -bfa_status_t -bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim, - struct bfa_itnim_ioprofile_s *ioprofile) -{ - struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(itnim->bfa); - if (!fcpim->io_profile) - return BFA_STATUS_IOPROFILE_OFF; - - itnim->ioprofile.index = BFA_IOBUCKET_MAX; - itnim->ioprofile.io_profile_start_time = - bfa_io_profile_start_time(itnim->bfa); - itnim->ioprofile.clock_res_mul = bfa_io_lat_clock_res_mul; - itnim->ioprofile.clock_res_div = bfa_io_lat_clock_res_div; - *ioprofile = itnim->ioprofile; - - return BFA_STATUS_OK; -} - void bfa_itnim_clear_stats(struct bfa_itnim_s *itnim) { @@ -2352,7 +2334,7 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim) scsi_for_each_sg(cmnd, sg, ioim->nsges, i) { if (i == 0) { /* build inline IO SG element */ - addr = bfa_os_sgaddr(sg_dma_address(sg)); + addr = bfa_sgaddr_le(sg_dma_address(sg)); sge->sga = *(union bfi_addr_u *) &addr; pgdlen = sg_dma_len(sg); sge->sg_len = pgdlen; @@ -2364,7 +2346,7 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim) if (sge_id == 0) sgpge = sgpg->sgpg->sges; - addr = bfa_os_sgaddr(sg_dma_address(sg)); + addr = bfa_sgaddr_le(sg_dma_address(sg)); sgpge->sga = *(union bfi_addr_u *) &addr; sgpge->sg_len = sg_dma_len(sg); pgcumsz += sgpge->sg_len; diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c index 141215c51635..e3a41b88a11b 100644 --- a/drivers/scsi/bfa/bfa_fcs.c +++ b/drivers/scsi/bfa/bfa_fcs.c @@ -19,9 +19,9 @@ * bfa_fcs.c BFA FCS main */ +#include "bfad_drv.h" #include "bfa_fcs.h" #include "bfa_fcbuild.h" -#include "bfad_drv.h" BFA_TRC_FILE(FCS, FCS); @@ -1097,7 +1097,7 @@ bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs, * external loopback cable is in place. Our own FLOGI frames are * sometimes looped back when switch port gets temporarily bypassed. */ - if ((pid == bfa_os_ntoh3b(FC_FABRIC_PORT)) && + if ((pid == bfa_ntoh3b(FC_FABRIC_PORT)) && (els_cmd->els_code == FC_ELS_FLOGI) && (flogi->port_name == bfa_fcs_lport_get_pwwn(&fabric->bport))) { bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOOPBACK); @@ -1107,7 +1107,7 @@ bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs, /* * FLOGI/EVFP exchanges should be consumed by base fabric. */ - if (fchs->d_id == bfa_os_hton3b(FC_FABRIC_PORT)) { + if (fchs->d_id == bfa_hton3b(FC_FABRIC_PORT)) { bfa_trc(fabric->fcs, pid); bfa_fcs_fabric_process_uf(fabric, fchs, len); return; @@ -1220,7 +1220,7 @@ bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric) return; reqlen = fc_flogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), - bfa_os_hton3b(FC_FABRIC_PORT), + bfa_hton3b(FC_FABRIC_PORT), n2n_port->reply_oxid, pcfg->pwwn, pcfg->nwwn, bfa_fcport_get_maxfrsize(bfa), diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h index e7977ee32992..f0e652b50994 100644 --- a/drivers/scsi/bfa/bfa_fcs.h +++ b/drivers/scsi/bfa/bfa_fcs.h @@ -61,7 +61,7 @@ struct bfa_fcs_s; #define N2N_LOCAL_PID 0x010000 #define N2N_REMOTE_PID 0x020000 #define BFA_FCS_RETRY_TIMEOUT 2000 -#define BFA_FCS_PID_IS_WKA(pid) ((bfa_os_ntoh3b(pid) > 0xFFF000) ? 1 : 0) +#define BFA_FCS_PID_IS_WKA(pid) ((bfa_ntoh3b(pid) > 0xFFF000) ? 1 : 0) diff --git a/drivers/scsi/bfa/bfa_fcs_fcpim.c b/drivers/scsi/bfa/bfa_fcs_fcpim.c index 82ac2798c545..5736ef8c592f 100644 --- a/drivers/scsi/bfa/bfa_fcs_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcs_fcpim.c @@ -19,9 +19,9 @@ * fcpim.c - FCP initiator mode i-t nexus state machine */ +#include "bfad_drv.h" #include "bfa_fcs.h" #include "bfa_fcbuild.h" -#include "bfad_drv.h" #include "bfad_im.h" BFA_TRC_FILE(FCS, FCPIM); diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c index 6e9151fecb74..7a2cf7713a95 100644 --- a/drivers/scsi/bfa/bfa_fcs_lport.c +++ b/drivers/scsi/bfa/bfa_fcs_lport.c @@ -15,10 +15,10 @@ * General Public License for more details. */ +#include "bfad_drv.h" #include "bfa_fcs.h" #include "bfa_fcbuild.h" #include "bfa_fc.h" -#include "bfad_drv.h" BFA_TRC_FILE(FCS, PORT); @@ -2818,7 +2818,7 @@ bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced) ms->fcxp = fcxp; len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), - bfa_os_hton3b(FC_MGMT_SERVER), + bfa_hton3b(FC_MGMT_SERVER), bfa_fcs_lport_get_fcid(port), 0, port->port_cfg.pwwn, port->port_cfg.nwwn, bfa_fcport_get_maxfrsize(port->fcs->bfa)); @@ -3575,7 +3575,7 @@ fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); ns->fcxp = fcxp; len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), - bfa_os_hton3b(FC_NAME_SERVER), + bfa_hton3b(FC_NAME_SERVER), bfa_fcs_lport_get_fcid(port), 0, port->port_cfg.pwwn, port->port_cfg.nwwn, bfa_fcport_get_maxfrsize(port->fcs->bfa)); @@ -4654,7 +4654,7 @@ bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index, while ((qe != qh) && (i < nrports)) { rport = (struct bfa_fcs_rport_s *) qe; - if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) { + if (bfa_ntoh3b(rport->pid) > 0xFFF000) { qe = bfa_q_next(qe); bfa_trc(fcs, (u32) rport->pwwn); bfa_trc(fcs, rport->pid); @@ -4702,7 +4702,7 @@ bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port, while ((qe != qh) && (i < *nrports)) { rport = (struct bfa_fcs_rport_s *) qe; - if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) { + if (bfa_ntoh3b(rport->pid) > 0xFFF000) { qe = bfa_q_next(qe); bfa_trc(fcs, (u32) rport->pwwn); bfa_trc(fcs, rport->pid); @@ -4753,7 +4753,7 @@ bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port) while (qe != qh) { rport = (struct bfa_fcs_rport_s *) qe; - if ((bfa_os_ntoh3b(rport->pid) > 0xFFF000) || + if ((bfa_ntoh3b(rport->pid) > 0xFFF000) || (bfa_fcs_rport_get_state(rport) == BFA_RPORT_OFFLINE)) { qe = bfa_q_next(qe); diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c index 2089d686fa5d..fbfcac7615b5 100644 --- a/drivers/scsi/bfa/bfa_fcs_rport.c +++ b/drivers/scsi/bfa/bfa_fcs_rport.c @@ -19,9 +19,9 @@ * rport.c Remote port implementation. */ +#include "bfad_drv.h" #include "bfa_fcs.h" #include "bfa_fcbuild.h" -#include "bfad_drv.h" BFA_TRC_FILE(FCS, RPORT); diff --git a/drivers/scsi/bfa/bfa_hw_cb.c b/drivers/scsi/bfa/bfa_hw_cb.c index d8464ae60070..1fa15edabcdd 100644 --- a/drivers/scsi/bfa/bfa_hw_cb.c +++ b/drivers/scsi/bfa/bfa_hw_cb.c @@ -15,6 +15,7 @@ * General Public License for more details. */ +#include "bfad_drv.h" #include "bfa_modules.h" #include "bfi_cbreg.h" diff --git a/drivers/scsi/bfa/bfa_hw_ct.c b/drivers/scsi/bfa/bfa_hw_ct.c index b0efbc713ffe..68077c4c4d55 100644 --- a/drivers/scsi/bfa/bfa_hw_ct.c +++ b/drivers/scsi/bfa/bfa_hw_ct.c @@ -15,6 +15,7 @@ * General Public License for more details. */ +#include "bfad_drv.h" #include "bfa_modules.h" #include "bfi_ctreg.h" diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index a8f745420f32..cd532444ffd9 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -15,11 +15,11 @@ * General Public License for more details. */ +#include "bfad_drv.h" #include "bfa_ioc.h" #include "bfi_ctreg.h" #include "bfa_defs.h" #include "bfa_defs_svc.h" -#include "bfad_drv.h" BFA_TRC_FILE(CNA, IOC); @@ -1428,12 +1428,12 @@ static void bfa_ioc_send_enable(struct bfa_ioc_s *ioc) { struct bfi_ioc_ctrl_req_s enable_req; - struct bfa_timeval_s tv; + struct timeval tv; bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ, bfa_ioc_portid(ioc)); enable_req.ioc_class = ioc->ioc_mc; - bfa_os_gettimeofday(&tv); + do_gettimeofday(&tv); enable_req.tv_sec = be32_to_cpu(tv.tv_sec); bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req_s)); } diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index 3c5bdd1c0c7f..62153f283216 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h @@ -18,7 +18,7 @@ #ifndef __BFA_IOC_H__ #define __BFA_IOC_H__ -#include "bfa_os_inc.h" +#include "bfad_drv.h" #include "bfa_cs.h" #include "bfi.h" @@ -74,7 +74,7 @@ struct bfa_sge_s { #define bfa_swap_words(_x) ( \ ((_x) << 32) | ((_x) >> 32)) -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN #define bfa_sge_to_be(_x) #define bfa_sge_to_le(_x) bfa_sge_word_swap(_x) #define bfa_sgaddr_le(_x) bfa_swap_words(_x) @@ -120,7 +120,7 @@ static inline void __bfa_dma_addr_set(union bfi_addr_u *dma_addr, u64 pa) { dma_addr->a32.addr_lo = (__be32) pa; - dma_addr->a32.addr_hi = (__be32) (bfa_os_u32(pa)); + dma_addr->a32.addr_hi = (__be32) (pa >> 32); } @@ -130,7 +130,7 @@ static inline void __bfa_dma_be_addr_set(union bfi_addr_u *dma_addr, u64 pa) { dma_addr->a32.addr_lo = cpu_to_be32(pa); - dma_addr->a32.addr_hi = cpu_to_be32(bfa_os_u32(pa)); + dma_addr->a32.addr_hi = cpu_to_be32(pa >> 32); } struct bfa_ioc_regs_s { diff --git a/drivers/scsi/bfa/bfa_ioc_cb.c b/drivers/scsi/bfa/bfa_ioc_cb.c index e9c8554e356e..a0e05da9df51 100644 --- a/drivers/scsi/bfa/bfa_ioc_cb.c +++ b/drivers/scsi/bfa/bfa_ioc_cb.c @@ -15,6 +15,7 @@ * General Public License for more details. */ +#include "bfad_drv.h" #include "bfa_ioc.h" #include "bfi_cbreg.h" #include "bfa_defs.h" diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c index 45d0ddc88c52..25a5d3c339c8 100644 --- a/drivers/scsi/bfa/bfa_ioc_ct.c +++ b/drivers/scsi/bfa/bfa_ioc_ct.c @@ -15,6 +15,7 @@ * General Public License for more details. */ +#include "bfad_drv.h" #include "bfa_ioc.h" #include "bfi_ctreg.h" #include "bfa_defs.h" diff --git a/drivers/scsi/bfa/bfa_os_inc.h b/drivers/scsi/bfa/bfa_os_inc.h deleted file mode 100644 index 65df62ef437f..000000000000 --- a/drivers/scsi/bfa/bfa_os_inc.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. - * All rights reserved - * www.brocade.com - * - * Linux driver for Brocade Fibre Channel Host Bus Adapter. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License (GPL) Version 2 as - * published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ - -#ifndef __BFA_OS_INC_H__ -#define __BFA_OS_INC_H__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __BIG_ENDIAN -#define __BIGENDIAN -#endif - -static inline u64 bfa_os_get_log_time(void) -{ - u64 system_time = 0; - struct timeval tv; - do_gettimeofday(&tv); - - /* We are interested in seconds only. */ - system_time = tv.tv_sec; - return system_time; -} - -#define bfa_io_lat_clock_res_div HZ -#define bfa_io_lat_clock_res_mul 1000 - -#define BFA_LOG(level, bfad, mask, fmt, arg...) \ -do { \ - if (((mask) == 4) || (level[1] <= '4')) \ - dev_printk(level, &((bfad)->pcidev)->dev, fmt, ##arg); \ -} while (0) - -#define bfa_swap_3b(_x) \ - ((((_x) & 0xff) << 16) | \ - ((_x) & 0x00ff00) | \ - (((_x) & 0xff0000) >> 16)) - -#define bfa_os_swap_sgaddr(_x) ((u64)( \ - (((u64)(_x) & (u64)0x00000000000000ffull) << 32) | \ - (((u64)(_x) & (u64)0x000000000000ff00ull) << 32) | \ - (((u64)(_x) & (u64)0x0000000000ff0000ull) << 32) | \ - (((u64)(_x) & (u64)0x00000000ff000000ull) << 32) | \ - (((u64)(_x) & (u64)0x000000ff00000000ull) >> 32) | \ - (((u64)(_x) & (u64)0x0000ff0000000000ull) >> 32) | \ - (((u64)(_x) & (u64)0x00ff000000000000ull) >> 32) | \ - (((u64)(_x) & (u64)0xff00000000000000ull) >> 32))) - -#ifndef __BIGENDIAN -#define bfa_os_hton3b(_x) bfa_swap_3b(_x) -#define bfa_os_sgaddr(_x) (_x) -#else -#define bfa_os_hton3b(_x) (_x) -#define bfa_os_sgaddr(_x) bfa_os_swap_sgaddr(_x) -#endif - -#define bfa_os_ntoh3b(_x) bfa_os_hton3b(_x) -#define bfa_os_u32(__pa64) ((__pa64) >> 32) - -#define BFA_TRC_TS(_trcm) \ - ({ \ - struct timeval tv; \ - \ - do_gettimeofday(&tv); \ - (tv.tv_sec*1000000+tv.tv_usec); \ - }) - -#define boolean_t int - -/* - * For current time stamp, OS API will fill-in - */ -struct bfa_timeval_s { - u32 tv_sec; /* seconds */ - u32 tv_usec; /* microseconds */ -}; - -static inline void -bfa_os_gettimeofday(struct bfa_timeval_s *tv) -{ - struct timeval tmp_tv; - - do_gettimeofday(&tmp_tv); - tv->tv_sec = (u32) tmp_tv.tv_sec; - tv->tv_usec = (u32) tmp_tv.tv_usec; -} - -static inline void -wwn2str(char *wwn_str, u64 wwn) -{ - union { - u64 wwn; - u8 byte[8]; - } w; - - w.wwn = wwn; - sprintf(wwn_str, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", w.byte[0], - w.byte[1], w.byte[2], w.byte[3], w.byte[4], w.byte[5], - w.byte[6], w.byte[7]); -} - -static inline void -fcid2str(char *fcid_str, u32 fcid) -{ - union { - u32 fcid; - u8 byte[4]; - } f; - - f.fcid = fcid; - sprintf(fcid_str, "%02x:%02x:%02x", f.byte[1], f.byte[2], f.byte[3]); -} - -#endif /* __BFA_OS_INC_H__ */ diff --git a/drivers/scsi/bfa/bfa_port.c b/drivers/scsi/bfa/bfa_port.c index 76efb9a5c324..45b3486cca9c 100644 --- a/drivers/scsi/bfa/bfa_port.c +++ b/drivers/scsi/bfa/bfa_port.c @@ -15,6 +15,7 @@ * General Public License for more details. */ +#include "bfad_drv.h" #include "bfa_defs_svc.h" #include "bfa_port.h" #include "bfi.h" @@ -36,7 +37,7 @@ bfa_port_stats_swap(struct bfa_port_s *port, union bfa_port_stats_u *stats) i += 2) { t0 = dip[i]; t1 = dip[i + 1]; -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN dip[i] = be32_to_cpu(t0); dip[i + 1] = be32_to_cpu(t1); #else @@ -96,13 +97,13 @@ bfa_port_get_stats_isr(struct bfa_port_s *port, bfa_status_t status) port->stats_busy = BFA_FALSE; if (status == BFA_STATUS_OK) { - struct bfa_timeval_s tv; + struct timeval tv; memcpy(port->stats, port->stats_dma.kva, sizeof(union bfa_port_stats_u)); bfa_port_stats_swap(port, port->stats); - bfa_os_gettimeofday(&tv); + do_gettimeofday(&tv); port->stats->fc.secs_reset = tv.tv_sec - port->stats_reset_time; } @@ -124,7 +125,7 @@ bfa_port_get_stats_isr(struct bfa_port_s *port, bfa_status_t status) static void bfa_port_clear_stats_isr(struct bfa_port_s *port, bfa_status_t status) { - struct bfa_timeval_s tv; + struct timeval tv; port->stats_status = status; port->stats_busy = BFA_FALSE; @@ -132,7 +133,7 @@ bfa_port_clear_stats_isr(struct bfa_port_s *port, bfa_status_t status) /* * re-initialize time stamp for stats reset */ - bfa_os_gettimeofday(&tv); + do_gettimeofday(&tv); port->stats_reset_time = tv.tv_sec; if (port->stats_cbfn) { @@ -432,7 +433,7 @@ void bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc, void *dev, struct bfa_trc_mod_s *trcmod) { - struct bfa_timeval_s tv; + struct timeval tv; bfa_assert(port); @@ -452,7 +453,7 @@ bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc, /* * initialize time stamp for stats reset */ - bfa_os_gettimeofday(&tv); + do_gettimeofday(&tv); port->stats_reset_time = tv.tv_sec; bfa_trc(port, 0); diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c index c9192869c0fe..1d5432b42a90 100644 --- a/drivers/scsi/bfa/bfa_svc.c +++ b/drivers/scsi/bfa/bfa_svc.c @@ -15,11 +15,10 @@ * General Public License for more details. */ -#include "bfa_os_inc.h" +#include "bfad_drv.h" #include "bfa_plog.h" #include "bfa_cs.h" #include "bfa_modules.h" -#include "bfad_drv.h" BFA_TRC_FILE(HAL, FCXP); BFA_MODULE(fcxp); @@ -286,6 +285,18 @@ plkd_validate_logrec(struct bfa_plog_rec_s *pl_rec) return 0; } +static u64 +bfa_get_log_time(void) +{ + u64 system_time = 0; + struct timeval tv; + do_gettimeofday(&tv); + + /* We are interested in seconds only. */ + system_time = tv.tv_sec; + return system_time; +} + static void bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec) { @@ -306,7 +317,7 @@ bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec) memcpy(pl_recp, pl_rec, sizeof(struct bfa_plog_rec_s)); - pl_recp->tv = bfa_os_get_log_time(); + pl_recp->tv = bfa_get_log_time(); BFA_PL_LOG_REC_INCR(plog->tail); if (plog->head == plog->tail) @@ -2728,7 +2739,7 @@ bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa); struct bfa_port_cfg_s *port_cfg = &fcport->cfg; struct bfa_fcport_ln_s *ln = &fcport->ln; - struct bfa_timeval_s tv; + struct timeval tv; memset(fcport, 0, sizeof(struct bfa_fcport_s)); fcport->bfa = bfa; @@ -2742,7 +2753,7 @@ bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, /* * initialize time stamp for stats reset */ - bfa_os_gettimeofday(&tv); + do_gettimeofday(&tv); fcport->stats_reset_time = tv.tv_sec; /* @@ -2967,7 +2978,7 @@ bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s *d, for (i = 0; i < ((sizeof(struct bfa_fcoe_stats_s))/sizeof(u32)); i = i + 2) { -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN dip[i] = be32_to_cpu(sip[i]); dip[i + 1] = be32_to_cpu(sip[i + 1]); #else @@ -2984,7 +2995,7 @@ __bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete) if (complete) { if (fcport->stats_status == BFA_STATUS_OK) { - struct bfa_timeval_s tv; + struct timeval tv; /* Swap FC QoS or FCoE stats */ if (bfa_ioc_get_fcmode(&fcport->bfa->ioc)) { @@ -2996,7 +3007,7 @@ __bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete) &fcport->stats_ret->fcoe, &fcport->stats->fcoe); - bfa_os_gettimeofday(&tv); + do_gettimeofday(&tv); fcport->stats_ret->fcoe.secs_reset = tv.tv_sec - fcport->stats_reset_time; } @@ -3055,12 +3066,12 @@ __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete) struct bfa_fcport_s *fcport = cbarg; if (complete) { - struct bfa_timeval_s tv; + struct timeval tv; /* * re-initialize time stamp for stats reset */ - bfa_os_gettimeofday(&tv); + do_gettimeofday(&tv); fcport->stats_reset_time = tv.tv_sec; fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status); @@ -4930,10 +4941,6 @@ bfa_uf_start(struct bfa_s *bfa) bfa_uf_post_all(BFA_UF_MOD(bfa)); } -/* - * hal_uf_api - */ - /* * Register handler for all unsolicted recieve frames. * diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index 2bc786212521..c80540e576cd 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -32,7 +32,6 @@ #include "bfad_drv.h" #include "bfad_im.h" #include "bfa_fcs.h" -#include "bfa_os_inc.h" #include "bfa_defs.h" #include "bfa.h" @@ -1102,15 +1101,15 @@ bfad_start_ops(struct bfad_s *bfad) { /* * If bfa_linkup_delay is set to -1 default; try to retrive the - * value using the bfad_os_get_linkup_delay(); else use the + * value using the bfad_get_linkup_delay(); else use the * passed in module param value as the bfa_linkup_delay. */ if (bfa_linkup_delay < 0) { - bfa_linkup_delay = bfad_os_get_linkup_delay(bfad); - bfad_os_rport_online_wait(bfad); + bfa_linkup_delay = bfad_get_linkup_delay(bfad); + bfad_rport_online_wait(bfad); bfa_linkup_delay = -1; } else - bfad_os_rport_online_wait(bfad); + bfad_rport_online_wait(bfad); BFA_LOG(KERN_INFO, bfad, bfa_log_level, "bfa device claimed\n"); diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c index d727f055bd8a..a94ea4235433 100644 --- a/drivers/scsi/bfa/bfad_attr.c +++ b/drivers/scsi/bfa/bfad_attr.c @@ -40,7 +40,7 @@ bfad_im_get_starget_port_id(struct scsi_target *starget) bfad = im_port->bfad; spin_lock_irqsave(&bfad->bfad_lock, flags); - itnim = bfad_os_get_itnim(im_port, starget->id); + itnim = bfad_get_itnim(im_port, starget->id); if (itnim) fc_id = bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim); @@ -66,7 +66,7 @@ bfad_im_get_starget_node_name(struct scsi_target *starget) bfad = im_port->bfad; spin_lock_irqsave(&bfad->bfad_lock, flags); - itnim = bfad_os_get_itnim(im_port, starget->id); + itnim = bfad_get_itnim(im_port, starget->id); if (itnim) node_name = bfa_fcs_itnim_get_nwwn(&itnim->fcs_itnim); @@ -92,7 +92,7 @@ bfad_im_get_starget_port_name(struct scsi_target *starget) bfad = im_port->bfad; spin_lock_irqsave(&bfad->bfad_lock, flags); - itnim = bfad_os_get_itnim(im_port, starget->id); + itnim = bfad_get_itnim(im_port, starget->id); if (itnim) port_name = bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim); @@ -111,7 +111,7 @@ bfad_im_get_host_port_id(struct Scsi_Host *shost) struct bfad_port_s *port = im_port->port; fc_host_port_id(shost) = - bfa_os_hton3b(bfa_fcs_lport_get_fcid(port->fcs_port)); + bfa_hton3b(bfa_fcs_lport_get_fcid(port->fcs_port)); } /* @@ -487,7 +487,7 @@ bfad_im_vport_delete(struct fc_vport *fc_vport) wait_for_completion(vport->comp_del); free_scsi_host: - bfad_os_scsi_host_free(bfad, im_port); + bfad_scsi_host_free(bfad, im_port); kfree(vport); diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h index b9bcb0b99b8a..24b6ab18f89d 100644 --- a/drivers/scsi/bfa/bfad_drv.h +++ b/drivers/scsi/bfa/bfad_drv.h @@ -26,7 +26,23 @@ #ifndef __BFAD_DRV_H__ #define __BFAD_DRV_H__ -#include "bfa_os_inc.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "bfa_modules.h" #include "bfa_fcs.h" @@ -272,19 +288,12 @@ do { \ } while (0) -#define list_remove_head(list, entry, type, member) \ -do { \ - entry = NULL; \ - if (!list_empty(list)) { \ - entry = list_entry((list)->next, type, member); \ - list_del_init(&entry->member); \ - } \ +#define BFA_LOG(level, bfad, mask, fmt, arg...) \ +do { \ + if (((mask) == 4) || (level[1] <= '4')) \ + dev_printk(level, &((bfad)->pcidev)->dev, fmt, ##arg); \ } while (0) -#define list_get_first(list, type, member) \ -((list_empty(list)) ? NULL : \ - list_entry((list)->next, type, member)) - bfa_status_t bfad_vport_create(struct bfad_s *bfad, u16 vf_id, struct bfa_lport_cfg_s *port_cfg, struct device *dev); @@ -316,8 +325,8 @@ void bfad_debugfs_exit(struct bfad_port_s *port); void bfad_pci_remove(struct pci_dev *pdev); int bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid); -void bfad_os_rport_online_wait(struct bfad_s *bfad); -int bfad_os_get_linkup_delay(struct bfad_s *bfad); +void bfad_rport_online_wait(struct bfad_s *bfad); +int bfad_get_linkup_delay(struct bfad_s *bfad); int bfad_install_msix_handler(struct bfad_s *bfad); extern struct idr bfad_im_port_index; diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index d10adcbf24b3..7b0f9725bbc9 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c @@ -92,10 +92,10 @@ bfa_cb_ioim_done(void *drv, struct bfad_ioim_s *dio, if (!cmnd->result && itnim && (bfa_lun_queue_depth > cmnd->device->queue_depth)) { /* Queue depth adjustment for good status completion */ - bfad_os_ramp_up_qdepth(itnim, cmnd->device); + bfad_ramp_up_qdepth(itnim, cmnd->device); } else if (cmnd->result == SAM_STAT_TASK_SET_FULL && itnim) { /* qfull handling */ - bfad_os_handle_qfull(itnim, cmnd->device); + bfad_handle_qfull(itnim, cmnd->device); } } @@ -123,7 +123,7 @@ bfa_cb_ioim_good_comp(void *drv, struct bfad_ioim_s *dio) if (itnim_data) { itnim = itnim_data->itnim; if (itnim) - bfad_os_ramp_up_qdepth(itnim, cmnd->device); + bfad_ramp_up_qdepth(itnim, cmnd->device); } } @@ -366,7 +366,7 @@ bfad_im_reset_bus_handler(struct scsi_cmnd *cmnd) spin_lock_irqsave(&bfad->bfad_lock, flags); for (i = 0; i < MAX_FCP_TARGET; i++) { - itnim = bfad_os_get_itnim(im_port, i); + itnim = bfad_get_itnim(im_port, i); if (itnim) { cmnd->SCp.ptr = (char *)&wq; rc = bfad_im_target_reset_send(bfad, cmnd, itnim); @@ -547,7 +547,7 @@ bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port, mutex_unlock(&bfad_mutex); - im_port->shost = bfad_os_scsi_host_alloc(im_port, bfad); + im_port->shost = bfad_scsi_host_alloc(im_port, bfad); if (!im_port->shost) { error = 1; goto out_free_idr; @@ -573,7 +573,7 @@ bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port, } /* setup host fixed attribute if the lk supports */ - bfad_os_fc_host_init(im_port); + bfad_fc_host_init(im_port); return 0; @@ -684,7 +684,7 @@ bfad_im_probe(struct bfad_s *bfad) bfad->im = im; im->bfad = bfad; - if (bfad_os_thread_workq(bfad) != BFA_STATUS_OK) { + if (bfad_thread_workq(bfad) != BFA_STATUS_OK) { kfree(im); rc = BFA_STATUS_FAILED; } @@ -697,14 +697,14 @@ void bfad_im_probe_undo(struct bfad_s *bfad) { if (bfad->im) { - bfad_os_destroy_workq(bfad->im); + bfad_destroy_workq(bfad->im); kfree(bfad->im); bfad->im = NULL; } } struct Scsi_Host * -bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *bfad) +bfad_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *bfad) { struct scsi_host_template *sht; @@ -719,7 +719,7 @@ bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *bfad) } void -bfad_os_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port) +bfad_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port) { if (!(im_port->flags & BFAD_PORT_DELETE)) flush_workqueue(bfad->im->drv_workq); @@ -729,7 +729,7 @@ bfad_os_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port) } void -bfad_os_destroy_workq(struct bfad_im_s *im) +bfad_destroy_workq(struct bfad_im_s *im) { if (im && im->drv_workq) { flush_workqueue(im->drv_workq); @@ -739,7 +739,7 @@ bfad_os_destroy_workq(struct bfad_im_s *im) } bfa_status_t -bfad_os_thread_workq(struct bfad_s *bfad) +bfad_thread_workq(struct bfad_s *bfad) { struct bfad_im_s *im = bfad->im; @@ -843,7 +843,7 @@ bfad_im_module_exit(void) } void -bfad_os_ramp_up_qdepth(struct bfad_itnim_s *itnim, struct scsi_device *sdev) +bfad_ramp_up_qdepth(struct bfad_itnim_s *itnim, struct scsi_device *sdev) { struct scsi_device *tmp_sdev; @@ -871,7 +871,7 @@ bfad_os_ramp_up_qdepth(struct bfad_itnim_s *itnim, struct scsi_device *sdev) } void -bfad_os_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev) +bfad_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev) { struct scsi_device *tmp_sdev; @@ -885,7 +885,7 @@ bfad_os_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev) } struct bfad_itnim_s * -bfad_os_get_itnim(struct bfad_im_port_s *im_port, int id) +bfad_get_itnim(struct bfad_im_port_s *im_port, int id) { struct bfad_itnim_s *itnim = NULL; @@ -946,7 +946,7 @@ bfad_im_supported_speeds(struct bfa_s *bfa) } void -bfad_os_fc_host_init(struct bfad_im_port_s *im_port) +bfad_fc_host_init(struct bfad_im_port_s *im_port) { struct Scsi_Host *host = im_port->shost; struct bfad_s *bfad = im_port->bfad; @@ -990,7 +990,7 @@ bfad_im_fc_rport_add(struct bfad_im_port_s *im_port, struct bfad_itnim_s *itnim) rport_ids.port_name = cpu_to_be64(bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim)); rport_ids.port_id = - bfa_os_hton3b(bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim)); + bfa_hton3b(bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim)); rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; itnim->fc_rport = fc_rport = @@ -1192,7 +1192,7 @@ out_fail_cmd: static DEF_SCSI_QCMD(bfad_im_queuecommand) void -bfad_os_rport_online_wait(struct bfad_s *bfad) +bfad_rport_online_wait(struct bfad_s *bfad) { int i; int rport_delay = 10; @@ -1220,7 +1220,7 @@ bfad_os_rport_online_wait(struct bfad_s *bfad) } int -bfad_os_get_linkup_delay(struct bfad_s *bfad) +bfad_get_linkup_delay(struct bfad_s *bfad) { u8 nwwns = 0; wwn_t wwns[BFA_PREBOOT_BOOTLUN_MAX]; diff --git a/drivers/scsi/bfa/bfad_im.h b/drivers/scsi/bfa/bfad_im.h index b038c0e08921..bfee63b16fa9 100644 --- a/drivers/scsi/bfa/bfad_im.h +++ b/drivers/scsi/bfa/bfad_im.h @@ -117,17 +117,17 @@ struct bfad_im_s { char drv_workq_name[KOBJ_NAME_LEN]; }; -struct Scsi_Host *bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port, +struct Scsi_Host *bfad_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *); -bfa_status_t bfad_os_thread_workq(struct bfad_s *bfad); -void bfad_os_destroy_workq(struct bfad_im_s *im); -void bfad_os_fc_host_init(struct bfad_im_port_s *im_port); -void bfad_os_scsi_host_free(struct bfad_s *bfad, +bfa_status_t bfad_thread_workq(struct bfad_s *bfad); +void bfad_destroy_workq(struct bfad_im_s *im); +void bfad_fc_host_init(struct bfad_im_port_s *im_port); +void bfad_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port); -void bfad_os_ramp_up_qdepth(struct bfad_itnim_s *itnim, +void bfad_ramp_up_qdepth(struct bfad_itnim_s *itnim, struct scsi_device *sdev); -void bfad_os_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev); -struct bfad_itnim_s *bfad_os_get_itnim(struct bfad_im_port_s *im_port, int id); +void bfad_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev); +struct bfad_itnim_s *bfad_get_itnim(struct bfad_im_port_s *im_port, int id); extern struct scsi_host_template bfad_im_scsi_host_template; extern struct scsi_host_template bfad_im_vport_template; diff --git a/drivers/scsi/bfa/bfi.h b/drivers/scsi/bfa/bfi.h index e19448427042..72b69a0c3b51 100644 --- a/drivers/scsi/bfa/bfi.h +++ b/drivers/scsi/bfa/bfi.h @@ -104,7 +104,7 @@ union bfi_addr_u { * Scatter Gather Element */ struct bfi_sge_s { -#ifdef __BIGENDIAN +#ifdef __BIG_ENDIAN u32 flags:2, rsvd:2, sg_len:28; -- cgit v1.2.3-59-g8ed1b From da99dcc98dd66a2de4864645bcafffd93cf5a62f Mon Sep 17 00:00:00 2001 From: Maggie Zhang Date: Thu, 9 Dec 2010 19:13:20 -0800 Subject: [SCSI] bfa: remove unused functions and misc cleanups Remove unused functions and fix checkpatch errors. Misc cleanups in comment and formatting. Signed-off-by: Maggie Zhang Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_core.c | 2 +- drivers/scsi/bfa/bfa_fcbuild.c | 7 +- drivers/scsi/bfa/bfa_fcpim.c | 340 ++++++--------------------------------- drivers/scsi/bfa/bfa_fcpim.h | 158 +++++++----------- drivers/scsi/bfa/bfa_fcs_lport.c | 3 +- drivers/scsi/bfa/bfa_fcs_rport.c | 3 +- drivers/scsi/bfa/bfa_ioc.c | 16 -- drivers/scsi/bfa/bfa_svc.c | 38 +---- 8 files changed, 110 insertions(+), 457 deletions(-) diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c index 02a5e04e365f..3f7f3742e72c 100644 --- a/drivers/scsi/bfa/bfa_core.c +++ b/drivers/scsi/bfa/bfa_core.c @@ -342,7 +342,7 @@ bfa_msix_lpu_err(struct bfa_s *bfa, int vec) intr = readl(bfa->iocfc.bfa_regs.intr_status); if (intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1)) - bfa_ioc_mbox_isr(&bfa->ioc); + bfa_ioc_mbox_isr(&bfa->ioc); intr &= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 | __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS | __HFN_INT_LL_HALT); diff --git a/drivers/scsi/bfa/bfa_fcbuild.c b/drivers/scsi/bfa/bfa_fcbuild.c index 1ca5af75dd37..b7e253451654 100644 --- a/drivers/scsi/bfa/bfa_fcbuild.c +++ b/drivers/scsi/bfa/bfa_fcbuild.c @@ -456,7 +456,7 @@ fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id, u32 s_id, return sizeof(struct fc_logo_s); } -static u16 +static u16 fc_adisc_x_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id, u32 s_id, __be16 ox_id, wwn_t port_name, wwn_t node_name, u8 els_code) @@ -807,11 +807,6 @@ fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc, return sizeof(struct fc_rpsc_acc_s); } -/* - * TBD - - * . get rid of unnecessary memsets - */ - u16 fc_logo_rsp_parse(struct fchs_s *fchs, int len) { diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c index 506f1d326e5b..314c93122980 100644 --- a/drivers/scsi/bfa/bfa_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcpim.c @@ -21,11 +21,6 @@ BFA_TRC_FILE(HAL, FCPIM); BFA_MODULE(fcpim); - -#define bfa_fcpim_add_iostats(__l, __r, __stats) \ - (__l->__stats += __r->__stats) - - /* * BFA ITNIM Related definitions */ @@ -73,10 +68,8 @@ static void bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim); } while (0) /* - * bfa_itnim_sm BFA itnim state machine + * itnim state machine event */ - - enum bfa_itnim_event { BFA_ITNIM_SM_CREATE = 1, /* itnim is created */ BFA_ITNIM_SM_ONLINE = 2, /* itnim is online */ @@ -228,7 +221,6 @@ static void __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete); static void __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete); static bfa_boolean_t bfa_ioim_is_abortable(struct bfa_ioim_s *ioim); - /* * forward declaration of BFA IO state machine */ @@ -256,7 +248,6 @@ static void bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim, enum bfa_ioim_event event); static void bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s *ioim, enum bfa_ioim_event event); - /* * forward declaration for BFA TSKIM functions */ @@ -271,7 +262,6 @@ static bfa_boolean_t bfa_tskim_send(struct bfa_tskim_s *tskim); static bfa_boolean_t bfa_tskim_send_abort(struct bfa_tskim_s *tskim); static void bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim); - /* * forward declaration of BFA TSKIM state machine */ @@ -289,13 +279,12 @@ static void bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim, enum bfa_tskim_event event); static void bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim, enum bfa_tskim_event event); - /* * BFA FCP Initiator Mode module */ /* - * Compute and return memory needed by FCP(im) module. + * Compute and return memory needed by FCP(im) module. */ static void bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len, @@ -378,56 +367,6 @@ bfa_fcpim_iocdisable(struct bfa_s *bfa) } } -void -bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *lstats, - struct bfa_itnim_iostats_s *rstats) -{ - bfa_fcpim_add_iostats(lstats, rstats, total_ios); - bfa_fcpim_add_iostats(lstats, rstats, qresumes); - bfa_fcpim_add_iostats(lstats, rstats, no_iotags); - bfa_fcpim_add_iostats(lstats, rstats, io_aborts); - bfa_fcpim_add_iostats(lstats, rstats, no_tskims); - bfa_fcpim_add_iostats(lstats, rstats, iocomp_ok); - bfa_fcpim_add_iostats(lstats, rstats, iocomp_underrun); - bfa_fcpim_add_iostats(lstats, rstats, iocomp_overrun); - bfa_fcpim_add_iostats(lstats, rstats, iocomp_aborted); - bfa_fcpim_add_iostats(lstats, rstats, iocomp_timedout); - bfa_fcpim_add_iostats(lstats, rstats, iocom_nexus_abort); - bfa_fcpim_add_iostats(lstats, rstats, iocom_proto_err); - bfa_fcpim_add_iostats(lstats, rstats, iocom_dif_err); - bfa_fcpim_add_iostats(lstats, rstats, iocom_sqer_needed); - bfa_fcpim_add_iostats(lstats, rstats, iocom_res_free); - bfa_fcpim_add_iostats(lstats, rstats, iocom_hostabrts); - bfa_fcpim_add_iostats(lstats, rstats, iocom_utags); - bfa_fcpim_add_iostats(lstats, rstats, io_cleanups); - bfa_fcpim_add_iostats(lstats, rstats, io_tmaborts); - bfa_fcpim_add_iostats(lstats, rstats, onlines); - bfa_fcpim_add_iostats(lstats, rstats, offlines); - bfa_fcpim_add_iostats(lstats, rstats, creates); - bfa_fcpim_add_iostats(lstats, rstats, deletes); - bfa_fcpim_add_iostats(lstats, rstats, create_comps); - bfa_fcpim_add_iostats(lstats, rstats, delete_comps); - bfa_fcpim_add_iostats(lstats, rstats, sler_events); - bfa_fcpim_add_iostats(lstats, rstats, fw_create); - bfa_fcpim_add_iostats(lstats, rstats, fw_delete); - bfa_fcpim_add_iostats(lstats, rstats, ioc_disabled); - bfa_fcpim_add_iostats(lstats, rstats, cleanup_comps); - bfa_fcpim_add_iostats(lstats, rstats, tm_cmnds); - bfa_fcpim_add_iostats(lstats, rstats, tm_fw_rsps); - bfa_fcpim_add_iostats(lstats, rstats, tm_success); - bfa_fcpim_add_iostats(lstats, rstats, tm_failures); - bfa_fcpim_add_iostats(lstats, rstats, tm_io_comps); - bfa_fcpim_add_iostats(lstats, rstats, tm_qresumes); - bfa_fcpim_add_iostats(lstats, rstats, tm_iocdowns); - bfa_fcpim_add_iostats(lstats, rstats, tm_cleanups); - bfa_fcpim_add_iostats(lstats, rstats, tm_cleanup_comps); - bfa_fcpim_add_iostats(lstats, rstats, io_comps); - bfa_fcpim_add_iostats(lstats, rstats, input_reqs); - bfa_fcpim_add_iostats(lstats, rstats, output_reqs); - bfa_fcpim_add_iostats(lstats, rstats, rd_throughput); - bfa_fcpim_add_iostats(lstats, rstats, wr_throughput); -} - void bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov) { @@ -446,128 +385,6 @@ bfa_fcpim_path_tov_get(struct bfa_s *bfa) return fcpim->path_tov / 1000; } -bfa_status_t -bfa_fcpim_port_iostats(struct bfa_s *bfa, struct bfa_itnim_iostats_s *stats, - u8 lp_tag) -{ - struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); - struct list_head *qe, *qen; - struct bfa_itnim_s *itnim; - - /* accumulate IO stats from itnim */ - memset(stats, 0, sizeof(struct bfa_itnim_iostats_s)); - list_for_each_safe(qe, qen, &fcpim->itnim_q) { - itnim = (struct bfa_itnim_s *) qe; - if (itnim->rport->rport_info.lp_tag != lp_tag) - continue; - bfa_fcpim_add_stats(stats, &(itnim->stats)); - } - return BFA_STATUS_OK; -} -bfa_status_t -bfa_fcpim_get_modstats(struct bfa_s *bfa, struct bfa_itnim_iostats_s *modstats) -{ - struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); - struct list_head *qe, *qen; - struct bfa_itnim_s *itnim; - - /* accumulate IO stats from itnim */ - memset(modstats, 0, sizeof(struct bfa_itnim_iostats_s)); - list_for_each_safe(qe, qen, &fcpim->itnim_q) { - itnim = (struct bfa_itnim_s *) qe; - bfa_fcpim_add_stats(modstats, &(itnim->stats)); - } - return BFA_STATUS_OK; -} - -bfa_status_t -bfa_fcpim_get_del_itn_stats(struct bfa_s *bfa, - struct bfa_fcpim_del_itn_stats_s *modstats) -{ - struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); - - *modstats = fcpim->del_itn_stats; - - return BFA_STATUS_OK; -} - - -bfa_status_t -bfa_fcpim_profile_on(struct bfa_s *bfa, u32 time) -{ - struct bfa_itnim_s *itnim; - struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); - struct list_head *qe, *qen; - - /* accumulate IO stats from itnim */ - list_for_each_safe(qe, qen, &fcpim->itnim_q) { - itnim = (struct bfa_itnim_s *) qe; - bfa_itnim_clear_stats(itnim); - } - fcpim->io_profile = BFA_TRUE; - fcpim->io_profile_start_time = time; - fcpim->profile_comp = bfa_ioim_profile_comp; - fcpim->profile_start = bfa_ioim_profile_start; - - return BFA_STATUS_OK; -} -bfa_status_t -bfa_fcpim_profile_off(struct bfa_s *bfa) -{ - struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); - fcpim->io_profile = BFA_FALSE; - fcpim->io_profile_start_time = 0; - fcpim->profile_comp = NULL; - fcpim->profile_start = NULL; - return BFA_STATUS_OK; -} - -bfa_status_t -bfa_fcpim_port_clear_iostats(struct bfa_s *bfa, u8 lp_tag) -{ - struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); - struct list_head *qe, *qen; - struct bfa_itnim_s *itnim; - - /* clear IO stats from all active itnims */ - list_for_each_safe(qe, qen, &fcpim->itnim_q) { - itnim = (struct bfa_itnim_s *) qe; - if (itnim->rport->rport_info.lp_tag != lp_tag) - continue; - bfa_itnim_clear_stats(itnim); - } - return BFA_STATUS_OK; - -} - -bfa_status_t -bfa_fcpim_clr_modstats(struct bfa_s *bfa) -{ - struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); - struct list_head *qe, *qen; - struct bfa_itnim_s *itnim; - - /* clear IO stats from all active itnims */ - list_for_each_safe(qe, qen, &fcpim->itnim_q) { - itnim = (struct bfa_itnim_s *) qe; - bfa_itnim_clear_stats(itnim); - } - memset(&fcpim->del_itn_stats, 0, - sizeof(struct bfa_fcpim_del_itn_stats_s)); - - return BFA_STATUS_OK; -} - -void -bfa_fcpim_qdepth_set(struct bfa_s *bfa, u16 q_depth) -{ - struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); - - bfa_assert(q_depth <= BFA_IOCFC_QDEPTH_MAX); - - fcpim->q_depth = q_depth; -} - u16 bfa_fcpim_qdepth_get(struct bfa_s *bfa) { @@ -576,32 +393,12 @@ bfa_fcpim_qdepth_get(struct bfa_s *bfa) return fcpim->q_depth; } -void -bfa_fcpim_update_ioredirect(struct bfa_s *bfa) -{ - bfa_boolean_t ioredirect; - - /* - * IO redirection is turned off when QoS is enabled and vice versa - */ - ioredirect = bfa_fcport_is_qos_enabled(bfa) ? BFA_FALSE : BFA_TRUE; -} - -void -bfa_fcpim_set_ioredirect(struct bfa_s *bfa, bfa_boolean_t state) -{ - struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); - fcpim->ioredirect = state; -} - - - /* * BFA ITNIM module state machine functions */ /* - * Beginning/unallocated state - no events expected. + * Beginning/unallocated state - no events expected. */ static void bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) @@ -622,7 +419,7 @@ bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) } /* - * Beginning state, only online event expected. + * Beginning state, only online event expected. */ static void bfa_itnim_sm_created(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) @@ -725,7 +522,7 @@ bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim, } /* - * Waiting for itnim create response from firmware, a delete is pending. + * Waiting for itnim create response from firmware, a delete is pending. */ static void bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim, @@ -753,7 +550,7 @@ bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim, } /* - * Online state - normal parking state. + * Online state - normal parking state. */ static void bfa_itnim_sm_online(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) @@ -795,7 +592,7 @@ bfa_itnim_sm_online(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) } /* - * Second level error recovery need. + * Second level error recovery need. */ static void bfa_itnim_sm_sler(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) @@ -826,7 +623,7 @@ bfa_itnim_sm_sler(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) } /* - * Going offline. Waiting for active IO cleanup. + * Going offline. Waiting for active IO cleanup. */ static void bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim, @@ -863,7 +660,7 @@ bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim, } /* - * Deleting itnim. Waiting for active IO cleanup. + * Deleting itnim. Waiting for active IO cleanup. */ static void bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim, @@ -948,7 +745,7 @@ bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim, } /* - * Offline state. + * Offline state. */ static void bfa_itnim_sm_offline(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) @@ -979,9 +776,6 @@ bfa_itnim_sm_offline(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) } } -/* - * IOC h/w failed state. - */ static void bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) @@ -1016,7 +810,7 @@ bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim, } /* - * Itnim is deleted, waiting for firmware response to delete. + * Itnim is deleted, waiting for firmware response to delete. */ static void bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) @@ -1061,7 +855,7 @@ bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim, } /* - * Initiate cleanup of all IOs on an IOC failure. + * Initiate cleanup of all IOs on an IOC failure. */ static void bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim) @@ -1095,7 +889,7 @@ bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim) } /* - * IO cleanup completion + * IO cleanup completion */ static void bfa_itnim_cleanp_comp(void *itnim_cbarg) @@ -1107,7 +901,7 @@ bfa_itnim_cleanp_comp(void *itnim_cbarg) } /* - * Initiate cleanup of all IOs. + * Initiate cleanup of all IOs. */ static void bfa_itnim_cleanup(struct bfa_itnim_s *itnim) @@ -1179,9 +973,6 @@ bfa_itnim_qresume(void *cbarg) bfa_sm_send_event(itnim, BFA_ITNIM_SM_QRESUME); } - - - /* * bfa_itnim_public */ @@ -1449,14 +1240,12 @@ bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim) fcpim->del_itn_stats.del_tm_iocdowns += itnim->stats.tm_iocdowns; } - - /* - * bfa_itnim_public + * bfa_itnim_public */ /* - * Itnim interrupt processing. + * Itnim interrupt processing. */ void bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m) @@ -1499,10 +1288,8 @@ bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m) } } - - /* - * bfa_itnim_api + * bfa_itnim_api */ struct bfa_itnim_s * @@ -1575,7 +1362,7 @@ bfa_itnim_clear_stats(struct bfa_itnim_s *itnim) */ /* - * IO is not started (unallocated). + * IO is not started (unallocated). */ static void bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) @@ -1640,7 +1427,7 @@ bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) } /* - * IO is waiting for SG pages. + * IO is waiting for SG pages. */ static void bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) @@ -1687,7 +1474,7 @@ bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) } /* - * IO is active. + * IO is active. */ static void bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) @@ -1771,8 +1558,8 @@ bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) } /* -* IO is retried with new tag. -*/ + * IO is retried with new tag. + */ static void bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) { @@ -1825,7 +1612,7 @@ bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) } /* - * IO is being aborted, waiting for completion from firmware. + * IO is being aborted, waiting for completion from firmware. */ static void bfa_ioim_sm_abort(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) @@ -1948,7 +1735,7 @@ bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) } /* - * IO is waiting for room in request CQ + * IO is waiting for room in request CQ */ static void bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) @@ -1992,7 +1779,7 @@ bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) } /* - * Active IO is being aborted, waiting for room in request CQ. + * Active IO is being aborted, waiting for room in request CQ. */ static void bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) @@ -2043,7 +1830,7 @@ bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) } /* - * Active IO is being cleaned up, waiting for room in request CQ. + * Active IO is being cleaned up, waiting for room in request CQ. */ static void bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) @@ -2297,7 +2084,7 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim) { struct bfa_itnim_s *itnim = ioim->itnim; struct bfi_ioim_req_s *m; - static struct fcp_cmnd_s cmnd_z0 = {{{0}}}; + static struct fcp_cmnd_s cmnd_z0 = { { { 0 } } }; struct bfi_sge_s *sge, *sgpge; u32 pgdlen = 0; u32 fcp_dl; @@ -2553,9 +2340,6 @@ bfa_ioim_is_abortable(struct bfa_ioim_s *ioim) return BFA_TRUE; } -/* - * or after the link comes back. - */ void bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim, bfa_boolean_t iotov) { @@ -2750,32 +2534,6 @@ bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m) bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD); } -void -bfa_ioim_profile_start(struct bfa_ioim_s *ioim) -{ - ioim->start_time = jiffies; -} - -void -bfa_ioim_profile_comp(struct bfa_ioim_s *ioim) -{ - struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio; - u32 fcp_dl = scsi_bufflen(cmnd); - u32 index = bfa_ioim_get_index(fcp_dl); - u64 end_time = jiffies; - struct bfa_itnim_latency_s *io_lat = - &(ioim->itnim->ioprofile.io_latency); - u32 val = (u32)(end_time - ioim->start_time); - - bfa_itnim_ioprofile_update(ioim->itnim, index); - - io_lat->count[index]++; - io_lat->min[index] = (io_lat->min[index] < val) ? - io_lat->min[index] : val; - io_lat->max[index] = (io_lat->max[index] > val) ? - io_lat->max[index] : val; - io_lat->avg[index] += val; -} /* * Called by itnim to clean up IO while going offline. */ @@ -2909,13 +2667,12 @@ bfa_ioim_abort(struct bfa_ioim_s *ioim) return BFA_STATUS_OK; } - /* * BFA TSKIM state machine functions */ /* - * Task management command beginning state. + * Task management command beginning state. */ static void bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim, enum bfa_tskim_event event) @@ -2952,9 +2709,8 @@ bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim, enum bfa_tskim_event event) } /* - * brief - * TM command is active, awaiting completion from firmware to - * cleanup IO requests in TM scope. + * TM command is active, awaiting completion from firmware to + * cleanup IO requests in TM scope. */ static void bfa_tskim_sm_active(struct bfa_tskim_s *tskim, enum bfa_tskim_event event) @@ -2989,8 +2745,8 @@ bfa_tskim_sm_active(struct bfa_tskim_s *tskim, enum bfa_tskim_event event) } /* - * An active TM is being cleaned up since ITN is offline. Awaiting cleanup - * completion event from firmware. + * An active TM is being cleaned up since ITN is offline. Awaiting cleanup + * completion event from firmware. */ static void bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event) @@ -3050,7 +2806,7 @@ bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event) } /* - * Task management command is waiting for room in request CQ + * Task management command is waiting for room in request CQ */ static void bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim, enum bfa_tskim_event event) @@ -3085,8 +2841,8 @@ bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim, enum bfa_tskim_event event) } /* - * Task management command is active, awaiting for room in request CQ - * to send clean up request. + * Task management command is active, awaiting for room in request CQ + * to send clean up request. */ static void bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim, @@ -3098,10 +2854,8 @@ bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim, case BFA_TSKIM_SM_DONE: bfa_reqq_wcancel(&tskim->reqq_wait); /* - * * Fall through !!! */ - case BFA_TSKIM_SM_QRESUME: bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup); bfa_tskim_send_abort(tskim); @@ -3120,7 +2874,7 @@ bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim, } /* - * BFA callback is pending + * BFA callback is pending */ static void bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim, enum bfa_tskim_event event) @@ -3145,7 +2899,6 @@ bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim, enum bfa_tskim_event event) } } - static void __bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete) { @@ -3175,7 +2928,7 @@ __bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete) BFI_TSKIM_STS_FAILED); } -static bfa_boolean_t +static bfa_boolean_t bfa_tskim_match_scope(struct bfa_tskim_s *tskim, struct scsi_lun lun) { switch (tskim->tm_cmnd) { @@ -3186,7 +2939,7 @@ bfa_tskim_match_scope(struct bfa_tskim_s *tskim, struct scsi_lun lun) case FCP_TM_CLEAR_TASK_SET: case FCP_TM_LUN_RESET: case FCP_TM_CLEAR_ACA: - return (!memcmp(&tskim->lun, &lun, sizeof(lun))); + return !memcmp(&tskim->lun, &lun, sizeof(lun)); default: bfa_assert(0); @@ -3196,7 +2949,7 @@ bfa_tskim_match_scope(struct bfa_tskim_s *tskim, struct scsi_lun lun) } /* - * Gather affected IO requests and task management commands. + * Gather affected IO requests and task management commands. */ static void bfa_tskim_gather_ios(struct bfa_tskim_s *tskim) @@ -3238,7 +2991,7 @@ bfa_tskim_gather_ios(struct bfa_tskim_s *tskim) } /* - * IO cleanup completion + * IO cleanup completion */ static void bfa_tskim_cleanp_comp(void *tskim_cbarg) @@ -3250,7 +3003,7 @@ bfa_tskim_cleanp_comp(void *tskim_cbarg) } /* - * Gather affected IO requests and task management commands. + * Gather affected IO requests and task management commands. */ static void bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim) @@ -3270,7 +3023,7 @@ bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim) } /* - * Send task management request to firmware. + * Send task management request to firmware. */ static bfa_boolean_t bfa_tskim_send(struct bfa_tskim_s *tskim) @@ -3305,7 +3058,7 @@ bfa_tskim_send(struct bfa_tskim_s *tskim) } /* - * Send abort request to cleanup an active TM to firmware. + * Send abort request to cleanup an active TM to firmware. */ static bfa_boolean_t bfa_tskim_send_abort(struct bfa_tskim_s *tskim) @@ -3336,7 +3089,7 @@ bfa_tskim_send_abort(struct bfa_tskim_s *tskim) } /* - * Call to resume task management cmnd waiting for room in request queue. + * Call to resume task management cmnd waiting for room in request queue. */ static void bfa_tskim_qresume(void *cbarg) @@ -3362,7 +3115,6 @@ bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim) } } - /* * Notification on completions from related ioim. */ @@ -3395,7 +3147,7 @@ bfa_tskim_cleanup(struct bfa_tskim_s *tskim) } /* - * Memory allocation and initialization. + * Memory allocation and initialization. */ void bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo) @@ -3477,7 +3229,7 @@ bfa_tskim_free(struct bfa_tskim_s *tskim) } /* - * Start a task management command. + * Start a task management command. * * @param[in] tskim BFA task management command instance * @param[in] itnim i-t nexus for the task management command diff --git a/drivers/scsi/bfa/bfa_fcpim.h b/drivers/scsi/bfa/bfa_fcpim.h index 7d0eababa5df..f9334587e02a 100644 --- a/drivers/scsi/bfa/bfa_fcpim.h +++ b/drivers/scsi/bfa/bfa_fcpim.h @@ -94,12 +94,12 @@ struct bfa_fcpim_mod_s { struct list_head ioim_resfree_q; /* IOs waiting for f/w */ struct list_head ioim_comp_q; /* IO global comp Q */ struct list_head tskim_free_q; - u32 ios_active; /* current active IOs */ - u32 delay_comp; + u32 ios_active; /* current active IOs */ + u32 delay_comp; struct bfa_fcpim_del_itn_stats_s del_itn_stats; bfa_boolean_t ioredirect; bfa_boolean_t io_profile; - u32 io_profile_start_time; + u32 io_profile_start_time; bfa_fcpim_profile_t profile_comp; bfa_fcpim_profile_t profile_start; }; @@ -114,25 +114,24 @@ struct bfa_ioim_s { struct bfa_fcpim_mod_s *fcpim; /* parent fcpim module */ struct bfa_itnim_s *itnim; /* i-t-n nexus for this IO */ struct bfad_ioim_s *dio; /* driver IO handle */ - u16 iotag; /* FWI IO tag */ - u16 abort_tag; /* unqiue abort request tag */ - u16 nsges; /* number of SG elements */ - u16 nsgpgs; /* number of SG pages */ + u16 iotag; /* FWI IO tag */ + u16 abort_tag; /* unqiue abort request tag */ + u16 nsges; /* number of SG elements */ + u16 nsgpgs; /* number of SG pages */ struct bfa_sgpg_s *sgpg; /* first SG page */ struct list_head sgpg_q; /* allocated SG pages */ struct bfa_cb_qe_s hcb_qe; /* bfa callback qelem */ bfa_cb_cbfn_t io_cbfn; /* IO completion handler */ - struct bfa_ioim_sp_s *iosp; /* slow-path IO handling */ - u8 reqq; /* Request queue for I/O */ - u64 start_time; /* IO's Profile start val */ + struct bfa_ioim_sp_s *iosp; /* slow-path IO handling */ + u8 reqq; /* Request queue for I/O */ + u64 start_time; /* IO's Profile start val */ }; - struct bfa_ioim_sp_s { struct bfi_msg_s comp_rspmsg; /* IO comp f/w response */ u8 *snsinfo; /* sense info for this IO */ - struct bfa_sgpg_wqe_s sgpg_wqe; /* waitq elem for sgpg */ - struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */ + struct bfa_sgpg_wqe_s sgpg_wqe; /* waitq elem for sgpg */ + struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */ bfa_boolean_t abort_explicit; /* aborted by OS */ struct bfa_tskim_s *tskim; /* Relevant TM cmd */ }; @@ -143,35 +142,34 @@ struct bfa_ioim_sp_s { struct bfa_tskim_s { struct list_head qe; bfa_sm_t sm; - struct bfa_s *bfa; /* BFA module */ + struct bfa_s *bfa; /* BFA module */ struct bfa_fcpim_mod_s *fcpim; /* parent fcpim module */ struct bfa_itnim_s *itnim; /* i-t-n nexus for this IO */ struct bfad_tskim_s *dtsk; /* driver task mgmt cmnd */ - bfa_boolean_t notify; /* notify itnim on TM comp */ + bfa_boolean_t notify; /* notify itnim on TM comp */ struct scsi_lun lun; /* lun if applicable */ - enum fcp_tm_cmnd tm_cmnd; /* task management command */ - u16 tsk_tag; /* FWI IO tag */ - u8 tsecs; /* timeout in seconds */ + enum fcp_tm_cmnd tm_cmnd; /* task management command */ + u16 tsk_tag; /* FWI IO tag */ + u8 tsecs; /* timeout in seconds */ struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */ struct list_head io_q; /* queue of affected IOs */ - struct bfa_wc_s wc; /* waiting counter */ + struct bfa_wc_s wc; /* waiting counter */ struct bfa_cb_qe_s hcb_qe; /* bfa callback qelem */ enum bfi_tskim_status tsk_status; /* TM status */ }; - /* * BFA i-t-n (initiator mode) */ struct bfa_itnim_s { - struct list_head qe; /* queue element */ - bfa_sm_t sm; /* i-t-n im BFA state machine */ - struct bfa_s *bfa; /* bfa instance */ - struct bfa_rport_s *rport; /* bfa rport */ - void *ditn; /* driver i-t-n structure */ + struct list_head qe; /* queue element */ + bfa_sm_t sm; /* i-t-n im BFA state machine */ + struct bfa_s *bfa; /* bfa instance */ + struct bfa_rport_s *rport; /* bfa rport */ + void *ditn; /* driver i-t-n structure */ struct bfi_mhdr_s mhdr; /* pre-built mhdr */ - u8 msg_no; /* itnim/rport firmware handle */ - u8 reqq; /* CQ for requests */ + u8 msg_no; /* itnim/rport firmware handle */ + u8 reqq; /* CQ for requests */ struct bfa_cb_qe_s hcb_qe; /* bfa callback qelem */ struct list_head pending_q; /* queue of pending IO requests */ struct list_head io_q; /* queue of active IO requests */ @@ -181,15 +179,14 @@ struct bfa_itnim_s { bfa_boolean_t seq_rec; /* SQER supported */ bfa_boolean_t is_online; /* itnim is ONLINE for IO */ bfa_boolean_t iotov_active; /* IO TOV timer is active */ - struct bfa_wc_s wc; /* waiting counter */ - struct bfa_timer_s timer; /* pending IO TOV */ + struct bfa_wc_s wc; /* waiting counter */ + struct bfa_timer_s timer; /* pending IO TOV */ struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */ struct bfa_fcpim_mod_s *fcpim; /* fcpim module */ struct bfa_itnim_iostats_s stats; struct bfa_itnim_ioprofile_s ioprofile; }; - #define bfa_itnim_is_online(_itnim) ((_itnim)->is_online) #define BFA_FCPIM_MOD(_hal) (&(_hal)->modules.fcpim_mod) #define BFA_IOIM_FROM_TAG(_fcpim, _iotag) \ @@ -246,32 +243,14 @@ void bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg); void bfa_itnim_iodone(struct bfa_itnim_s *itnim); void bfa_itnim_tskdone(struct bfa_itnim_s *itnim); bfa_boolean_t bfa_itnim_hold_io(struct bfa_itnim_s *itnim); -void bfa_ioim_profile_comp(struct bfa_ioim_s *ioim); -void bfa_ioim_profile_start(struct bfa_ioim_s *ioim); - /* * bfa fcpim module API functions */ -void bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov); +void bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov); u16 bfa_fcpim_path_tov_get(struct bfa_s *bfa); -void bfa_fcpim_qdepth_set(struct bfa_s *bfa, u16 q_depth); u16 bfa_fcpim_qdepth_get(struct bfa_s *bfa); -bfa_status_t bfa_fcpim_get_modstats(struct bfa_s *bfa, - struct bfa_itnim_iostats_s *modstats); -bfa_status_t bfa_fcpim_port_iostats(struct bfa_s *bfa, - struct bfa_itnim_iostats_s *stats, u8 lp_tag); -bfa_status_t bfa_fcpim_get_del_itn_stats(struct bfa_s *bfa, - struct bfa_fcpim_del_itn_stats_s *modstats); -bfa_status_t bfa_fcpim_port_clear_iostats(struct bfa_s *bfa, u8 lp_tag); -void bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *fcpim_stats, - struct bfa_itnim_iostats_s *itnim_stats); -bfa_status_t bfa_fcpim_clr_modstats(struct bfa_s *bfa); -void bfa_fcpim_set_ioredirect(struct bfa_s *bfa, - bfa_boolean_t state); -void bfa_fcpim_update_ioredirect(struct bfa_s *bfa); -bfa_status_t bfa_fcpim_profile_on(struct bfa_s *bfa, u32 time); -bfa_status_t bfa_fcpim_profile_off(struct bfa_s *bfa); + #define bfa_fcpim_ioredirect_enabled(__bfa) \ (((struct bfa_fcpim_mod_s *)(BFA_FCPIM_MOD(__bfa)))->ioredirect) @@ -289,46 +268,33 @@ bfa_status_t bfa_fcpim_profile_off(struct bfa_s *bfa); * bfa itnim API functions */ struct bfa_itnim_s *bfa_itnim_create(struct bfa_s *bfa, - struct bfa_rport_s *rport, void *itnim); -void bfa_itnim_delete(struct bfa_itnim_s *itnim); -void bfa_itnim_online(struct bfa_itnim_s *itnim, - bfa_boolean_t seq_rec); -void bfa_itnim_offline(struct bfa_itnim_s *itnim); -void bfa_itnim_clear_stats(struct bfa_itnim_s *itnim); -bfa_status_t bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim, - struct bfa_itnim_ioprofile_s *ioprofile); + struct bfa_rport_s *rport, void *itnim); +void bfa_itnim_delete(struct bfa_itnim_s *itnim); +void bfa_itnim_online(struct bfa_itnim_s *itnim, bfa_boolean_t seq_rec); +void bfa_itnim_offline(struct bfa_itnim_s *itnim); +void bfa_itnim_clear_stats(struct bfa_itnim_s *itnim); +bfa_status_t bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim, + struct bfa_itnim_ioprofile_s *ioprofile); + #define bfa_itnim_get_reqq(__ioim) (((struct bfa_ioim_s *)__ioim)->itnim->reqq) /* - * BFA completion callback for bfa_itnim_online(). - * - * @param[in] itnim FCS or driver itnim instance - * - * return None + * BFA completion callback for bfa_itnim_online(). */ void bfa_cb_itnim_online(void *itnim); /* - * BFA completion callback for bfa_itnim_offline(). - * - * @param[in] itnim FCS or driver itnim instance - * - * return None + * BFA completion callback for bfa_itnim_offline(). */ void bfa_cb_itnim_offline(void *itnim); void bfa_cb_itnim_tov_begin(void *itnim); void bfa_cb_itnim_tov(void *itnim); /* - * BFA notification to FCS/driver for second level error recovery. - * + * BFA notification to FCS/driver for second level error recovery. * Atleast one I/O request has timedout and target is unresponsive to * repeated abort requests. Second level error recovery should be initiated * by starting implicit logout and recovery procedures. - * - * @param[in] itnim FCS or driver itnim instance - * - * return None */ void bfa_cb_itnim_sler(void *itnim); @@ -345,10 +311,8 @@ void bfa_ioim_start(struct bfa_ioim_s *ioim); bfa_status_t bfa_ioim_abort(struct bfa_ioim_s *ioim); void bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim, bfa_boolean_t iotov); - - /* - * I/O completion notification. + * I/O completion notification. * * @param[in] dio driver IO structure * @param[in] io_status IO completion status @@ -359,39 +323,31 @@ void bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim, * * @return None */ -void bfa_cb_ioim_done(void *bfad, struct bfad_ioim_s *dio, - enum bfi_ioim_status io_status, - u8 scsi_status, int sns_len, - u8 *sns_info, s32 residue); +void bfa_cb_ioim_done(void *bfad, struct bfad_ioim_s *dio, + enum bfi_ioim_status io_status, + u8 scsi_status, int sns_len, + u8 *sns_info, s32 residue); /* - * I/O good completion notification. - * - * @param[in] dio driver IO structure - * - * @return None + * I/O good completion notification. */ -void bfa_cb_ioim_good_comp(void *bfad, struct bfad_ioim_s *dio); +void bfa_cb_ioim_good_comp(void *bfad, struct bfad_ioim_s *dio); /* - * I/O abort completion notification - * - * @param[in] dio driver IO that was aborted - * - * @return None + * I/O abort completion notification */ -void bfa_cb_ioim_abort(void *bfad, struct bfad_ioim_s *dio); +void bfa_cb_ioim_abort(void *bfad, struct bfad_ioim_s *dio); /* * bfa tskim API functions */ -struct bfa_tskim_s *bfa_tskim_alloc(struct bfa_s *bfa, - struct bfad_tskim_s *dtsk); -void bfa_tskim_free(struct bfa_tskim_s *tskim); -void bfa_tskim_start(struct bfa_tskim_s *tskim, - struct bfa_itnim_s *itnim, struct scsi_lun lun, - enum fcp_tm_cmnd tm, u8 t_secs); -void bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk, - enum bfi_tskim_status tsk_status); +struct bfa_tskim_s *bfa_tskim_alloc(struct bfa_s *bfa, + struct bfad_tskim_s *dtsk); +void bfa_tskim_free(struct bfa_tskim_s *tskim); +void bfa_tskim_start(struct bfa_tskim_s *tskim, + struct bfa_itnim_s *itnim, struct scsi_lun lun, + enum fcp_tm_cmnd tm, u8 t_secs); +void bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk, + enum bfi_tskim_status tsk_status); #endif /* __BFA_FCPIM_H__ */ diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c index 7a2cf7713a95..aa4516672eed 100644 --- a/drivers/scsi/bfa/bfa_fcs_lport.c +++ b/drivers/scsi/bfa/bfa_fcs_lport.c @@ -883,7 +883,8 @@ bfa_fcs_lport_get_attr( if (port->fabric) { port_attr->port_type = port->fabric->oper_type; - port_attr->loopback = bfa_sm_cmp_state(port->fabric, bfa_fcs_fabric_sm_loopback); + port_attr->loopback = bfa_sm_cmp_state(port->fabric, + bfa_fcs_fabric_sm_loopback); port_attr->authfail = bfa_sm_cmp_state(port->fabric, bfa_fcs_fabric_sm_auth_failed); diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c index fbfcac7615b5..711f2d992a97 100644 --- a/drivers/scsi/bfa/bfa_fcs_rport.c +++ b/drivers/scsi/bfa/bfa_fcs_rport.c @@ -1974,7 +1974,8 @@ bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid) rport->itnim = bfa_fcs_itnim_create(rport); if (!rport->itnim) { bfa_trc(fcs, rpid); - bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_DELETE); + bfa_sm_send_event(rport->bfa_rport, + BFA_RPORT_SM_DELETE); kfree(rport_drv); return NULL; } diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index cd532444ffd9..c4d56506e966 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -586,13 +586,10 @@ bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event) } } - - /* * IOCPF State Machine */ - /* * Reset entry actions -- initialize state machine */ @@ -754,7 +751,6 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf_s *iocpf, enum iocpf_event event) } } - static void bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf_s *iocpf) { @@ -811,7 +807,6 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event) } } - static void bfa_iocpf_sm_enabling_entry(struct bfa_iocpf_s *iocpf) { @@ -873,8 +868,6 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event) } } - - static void bfa_iocpf_sm_ready_entry(struct bfa_iocpf_s *iocpf) { @@ -915,7 +908,6 @@ bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event) } } - static void bfa_iocpf_sm_disabling_entry(struct bfa_iocpf_s *iocpf) { @@ -990,7 +982,6 @@ bfa_iocpf_sm_disabled(struct bfa_iocpf_s *iocpf, enum iocpf_event event) } } - static void bfa_iocpf_sm_initfail_entry(struct bfa_iocpf_s *iocpf) { @@ -1028,7 +1019,6 @@ bfa_iocpf_sm_initfail(struct bfa_iocpf_s *iocpf, enum iocpf_event event) } } - static void bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf) { @@ -1078,8 +1068,6 @@ bfa_iocpf_sm_fail(struct bfa_iocpf_s *iocpf, enum iocpf_event event) } } - - /* * BFA IOC private functions */ @@ -1123,7 +1111,6 @@ bfa_ioc_sem_get(void __iomem *sem_reg) return BFA_FALSE; } - static void bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc) { @@ -1305,7 +1292,6 @@ bfa_ioc_msgflush(struct bfa_ioc_s *ioc) writel(1, ioc->ioc_regs.lpu_mbox_cmd); } - static void bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force) { @@ -1738,7 +1724,6 @@ bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz) return BFA_STATUS_OK; } - static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc) { @@ -1752,7 +1737,6 @@ bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc) "with the driver version\n"); } - bfa_status_t bfa_ioc_pll_init(struct bfa_ioc_s *ioc) { diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c index 1d5432b42a90..8dc2e7752e4c 100644 --- a/drivers/scsi/bfa/bfa_svc.c +++ b/drivers/scsi/bfa/bfa_svc.c @@ -52,7 +52,6 @@ BFA_MODULE(uf); ((bfa_fcport_is_disabled(bfa) == BFA_TRUE) || \ (bfa_ioc_is_disabled(&bfa->ioc) == BFA_TRUE)) - /* * BFA port state machine events */ @@ -916,10 +915,6 @@ bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req) bfa_trc(bfa, bfa_reqq_ci(bfa, BFA_REQQ_FCXP)); } -/* - * hal_fcxp_api BFA FCXP API - */ - /* * Allocate an FCXP instance to send a response or to send a request * that has a response. Request/response buffers are allocated by caller. @@ -1014,7 +1009,7 @@ bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp) } /* - * Free the BFA FCXP + * Free the BFA FCXP * * @param[in] fcxp BFA fcxp pointer * @@ -1161,12 +1156,6 @@ bfa_fcxp_discard(struct bfa_fcxp_s *fcxp) fcxp->send_cbfn = bfa_fcxp_null_comp; } - - -/* - * hal_fcxp_public BFA FCXP public functions - */ - void bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg) { @@ -2636,12 +2625,6 @@ bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln, } } - - -/* - * hal_port_private - */ - static void __bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete) { @@ -3229,12 +3212,6 @@ bfa_trunk_iocdisable(struct bfa_s *bfa) } } - - -/* - * hal_port_public - */ - /* * Called to initialize port attributes */ @@ -3336,12 +3313,6 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg) } } - - -/* - * hal_port_api - */ - /* * Registered callback for port events. */ @@ -3674,7 +3645,6 @@ bfa_fcport_is_ratelim(struct bfa_s *bfa) } - /* * Get default minimum ratelim speed */ @@ -4573,12 +4543,6 @@ bfa_sgpg_iocdisable(struct bfa_s *bfa) { } - - -/* - * hal_sgpg_public BFA SGPG public functions - */ - bfa_status_t bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs) { -- cgit v1.2.3-59-g8ed1b From 4e78efefa3c083240bd47153ffa99642bfdc7811 Mon Sep 17 00:00:00 2001 From: Krishna Gudipati Date: Mon, 13 Dec 2010 16:16:09 -0800 Subject: [SCSI] bfa: IOC fwtrace save logic & state machine fixes. - Move fw trace save logic to bfa_ioc_sm_fail_entry(), so that fw trace is saved irrespective of the cause of the failure. - Make bfa_ioc_sm_fail() a failure parking state. - Rename bfa_ioc_sm_initfail() to a more appropriate bfa_ioc_sm_fail_retry() as it is no longer a parking state. Signed-off-by: Krishna Gudipati Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_ioc.c | 141 ++++++++++++++++++++++++--------------------- 1 file changed, 74 insertions(+), 67 deletions(-) diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index c4d56506e966..9173bf20ffba 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -88,6 +88,8 @@ static void bfa_ioc_recover(struct bfa_ioc_s *ioc); static void bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc); static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc); static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc); +static void bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc); +static void bfa_ioc_fail_notify(struct bfa_ioc_s *ioc); static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc); @@ -102,7 +104,7 @@ enum ioc_event { IOC_E_ENABLED = 5, /* f/w enabled */ IOC_E_FWRSP_GETATTR = 6, /* IOC get attribute response */ IOC_E_DISABLED = 7, /* f/w disabled */ - IOC_E_FAILED = 8, /* failure notice by iocpf sm */ + IOC_E_PFFAILED = 8, /* failure notice by iocpf sm */ IOC_E_HBFAIL = 9, /* heartbeat failure */ IOC_E_HWERROR = 10, /* hardware error interrupt */ IOC_E_TIMEOUT = 11, /* timeout */ @@ -113,7 +115,7 @@ bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc_s, enum ioc_event); bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc_s, enum ioc_event); bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc_s, enum ioc_event); bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc_s, enum ioc_event); -bfa_fsm_state_decl(bfa_ioc, initfail, struct bfa_ioc_s, enum ioc_event); +bfa_fsm_state_decl(bfa_ioc, fail_retry, struct bfa_ioc_s, enum ioc_event); bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc_s, enum ioc_event); bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event); bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event); @@ -124,7 +126,7 @@ static struct bfa_sm_table_s ioc_sm_table[] = { {BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_ENABLING}, {BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR}, {BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL}, - {BFA_SM(bfa_ioc_sm_initfail), BFA_IOC_INITFAIL}, + {BFA_SM(bfa_ioc_sm_fail_retry), BFA_IOC_INITFAIL}, {BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL}, {BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING}, {BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED}, @@ -298,13 +300,13 @@ bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event) bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr); break; - case IOC_E_FAILED: - bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); - break; - + case IOC_E_PFFAILED: + /* !!! fall through !!! */ case IOC_E_HWERROR: - bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); - bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL); + ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); + bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry); + if (event != IOC_E_PFFAILED) + bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL); break; case IOC_E_DISABLE: @@ -347,18 +349,16 @@ bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event) bfa_fsm_set_state(ioc, bfa_ioc_sm_op); break; - case IOC_E_FAILED: - bfa_ioc_timer_stop(ioc); - bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); break; - + case IOC_E_PFFAILED: case IOC_E_HWERROR: bfa_ioc_timer_stop(ioc); - /* fall through */ - + /* !!! fall through !!! */ case IOC_E_TIMEOUT: - bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); - bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL); + ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); + bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry); + if (event != IOC_E_PFFAILED) + bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL); break; case IOC_E_DISABLE: @@ -399,18 +399,20 @@ bfa_ioc_sm_op(struct bfa_ioc_s *ioc, enum ioc_event event) bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling); break; - case IOC_E_FAILED: - bfa_hb_timer_stop(ioc); - bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); - break; - + case IOC_E_PFFAILED: case IOC_E_HWERROR: bfa_hb_timer_stop(ioc); /* !!! fall through !!! */ - case IOC_E_HBFAIL: - bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); - bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL); + bfa_ioc_fail_notify(ioc); + + if (ioc->iocpf.auto_recover) + bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry); + else + bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); + + if (event != IOC_E_PFFAILED) + bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL); break; default: @@ -489,16 +491,16 @@ bfa_ioc_sm_disabled(struct bfa_ioc_s *ioc, enum ioc_event event) static void -bfa_ioc_sm_initfail_entry(struct bfa_ioc_s *ioc) +bfa_ioc_sm_fail_retry_entry(struct bfa_ioc_s *ioc) { - ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); + bfa_trc(ioc, 0); } /* * Hardware initialization failed. */ static void -bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event) +bfa_ioc_sm_fail_retry(struct bfa_ioc_s *ioc, enum ioc_event event) { bfa_trc(ioc, event); @@ -507,11 +509,17 @@ bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event) bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr); break; - case IOC_E_FAILED: + case IOC_E_PFFAILED: + case IOC_E_HWERROR: /* - * Initialization failure during iocpf init retry. + * Initialization retry failed. */ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); + if (event != IOC_E_PFFAILED) + bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL); + break; + + case IOC_E_ENABLE: break; case IOC_E_DISABLE: @@ -532,21 +540,7 @@ bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event) static void bfa_ioc_sm_fail_entry(struct bfa_ioc_s *ioc) { - struct list_head *qe; - struct bfa_ioc_hbfail_notify_s *notify; - struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad; - - /* - * Notify driver and common modules registered for notification. - */ - ioc->cbfn->hbfail_cbfn(ioc->bfa); - list_for_each(qe, &ioc->hb_notify_q) { - notify = (struct bfa_ioc_hbfail_notify_s *) qe; - notify->cbfn(notify->cbarg); - } - - BFA_LOG(KERN_CRIT, bfad, bfa_log_level, - "Heart Beat of IOC has failed\n"); + bfa_trc(ioc, 0); } /* @@ -559,19 +553,10 @@ bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event) switch (event) { - case IOC_E_FAILED: - /* - * Initialization failure during iocpf recovery. - * !!! Fall through !!! - */ case IOC_E_ENABLE: ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); break; - case IOC_E_ENABLED: - bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr); - break; - case IOC_E_DISABLE: bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling); break; @@ -793,7 +778,7 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event) bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); if (event == IOCPF_E_TIMEOUT) - bfa_fsm_send_event(ioc, IOC_E_FAILED); + bfa_fsm_send_event(ioc, IOC_E_PFFAILED); break; case IOCPF_E_DISABLE: @@ -850,7 +835,7 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event) bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); if (event == IOCPF_E_TIMEOUT) - bfa_fsm_send_event(ioc, IOC_E_FAILED); + bfa_fsm_send_event(ioc, IOC_E_PFFAILED); break; case IOCPF_E_DISABLE: @@ -900,7 +885,7 @@ bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event) else bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); - bfa_fsm_send_event(ioc, IOC_E_FAILED); + bfa_fsm_send_event(ioc, IOC_E_PFFAILED); break; default: @@ -1724,6 +1709,29 @@ bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz) return BFA_STATUS_OK; } +static void +bfa_ioc_fail_notify(struct bfa_ioc_s *ioc) +{ + struct list_head *qe; + struct bfa_ioc_hbfail_notify_s *notify; + struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad; + + /** + * Notify driver and common modules registered for notification. + */ + ioc->cbfn->hbfail_cbfn(ioc->bfa); + list_for_each(qe, &ioc->hb_notify_q) { + notify = (struct bfa_ioc_hbfail_notify_s *) qe; + notify->cbfn(notify->cbarg); + } + + bfa_ioc_debug_save_ftrc(ioc); + + BFA_LOG(KERN_CRIT, bfad, bfa_log_level, + "Heart Beat of IOC has failed\n"); + +} + static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc) { @@ -2187,7 +2195,8 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc, bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver); ad_attr->cna_capable = ioc->cna; - ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna; + ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna && + !ad_attr->is_mezz; } enum bfa_ioc_type_e @@ -2530,13 +2539,16 @@ bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc) * Save firmware trace if configured. */ static void -bfa_ioc_debug_save(struct bfa_ioc_s *ioc) +bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc) { int tlen; - if (ioc->dbg_fwsave_len) { - tlen = ioc->dbg_fwsave_len; - bfa_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen); + if (ioc->dbg_fwsave_once) { + ioc->dbg_fwsave_once = BFA_FALSE; + if (ioc->dbg_fwsave_len) { + tlen = ioc->dbg_fwsave_len; + bfa_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen); + } } } @@ -2546,11 +2558,6 @@ bfa_ioc_debug_save(struct bfa_ioc_s *ioc) static void bfa_ioc_recover(struct bfa_ioc_s *ioc) { - if (ioc->dbg_fwsave_once) { - ioc->dbg_fwsave_once = BFA_FALSE; - bfa_ioc_debug_save(ioc); - } - bfa_ioc_stats(ioc, ioc_hbfails); bfa_fsm_send_event(ioc, IOC_E_HBFAIL); } -- cgit v1.2.3-59-g8ed1b From f3a060ca57903daaf2f1a88c6c25832619b2a74f Mon Sep 17 00:00:00 2001 From: Krishna Gudipati Date: Mon, 13 Dec 2010 16:16:50 -0800 Subject: [SCSI] bfa: Store port configuration in flash for persistency. When the bfa driver is loaded a flogi is sent without the knowledge of trunking configuration. This normal flogi causes the switch ports which had trunking enabled to go to persistent offline. Solution is to store the port configuration (which has trunking info) in the flash for persistency. The firmware will read this configuration when the very first fcport enable is received. Signed-off-by: Krishna Gudipati Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_svc.c | 25 ++++++++++++++++++++++++- drivers/scsi/bfa/bfa_svc.h | 1 + drivers/scsi/bfa/bfi_ms.h | 6 ++++-- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c index 8dc2e7752e4c..2666472d1429 100644 --- a/drivers/scsi/bfa/bfa_svc.c +++ b/drivers/scsi/bfa/bfa_svc.c @@ -1890,6 +1890,8 @@ bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport, /* * Start event after IOC is configured and BFA is started. */ + fcport->use_flash_cfg = BFA_TRUE; + if (bfa_fcport_send_enable(fcport)) { bfa_trc(fcport->bfa, BFA_TRUE); bfa_sm_set_state(fcport, bfa_fcport_sm_enabling); @@ -2855,6 +2857,7 @@ bfa_fcport_send_enable(struct bfa_fcport_s *fcport) m->port_cfg = fcport->cfg; m->msgtag = fcport->msgtag; m->port_cfg.maxfrsize = cpu_to_be16(fcport->cfg.maxfrsize); + m->use_flash_cfg = fcport->use_flash_cfg; bfa_dma_be_addr_set(m->stats_dma_addr, fcport->stats_pa); bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_lo); bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_hi); @@ -3251,8 +3254,28 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg) switch (msg->mhdr.msg_id) { case BFI_FCPORT_I2H_ENABLE_RSP: - if (fcport->msgtag == i2hmsg.penable_rsp->msgtag) + if (fcport->msgtag == i2hmsg.penable_rsp->msgtag) { + + if (fcport->use_flash_cfg) { + fcport->cfg = i2hmsg.penable_rsp->port_cfg; + fcport->cfg.maxfrsize = + cpu_to_be16(fcport->cfg.maxfrsize); + fcport->cfg.path_tov = + cpu_to_be16(fcport->cfg.path_tov); + fcport->cfg.q_depth = + cpu_to_be16(fcport->cfg.q_depth); + + if (fcport->cfg.trunked) + fcport->trunk.attr.state = + BFA_TRUNK_OFFLINE; + else + fcport->trunk.attr.state = + BFA_TRUNK_DISABLED; + fcport->use_flash_cfg = BFA_FALSE; + } + bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP); + } break; case BFI_FCPORT_I2H_DISABLE_RSP: diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h index 29b091826e9b..36c81c74f04a 100644 --- a/drivers/scsi/bfa/bfa_svc.h +++ b/drivers/scsi/bfa/bfa_svc.h @@ -444,6 +444,7 @@ struct bfa_fcport_s { u8 myalpa; /* my ALPA in LOOP topology */ u8 rsvd[3]; struct bfa_port_cfg_s cfg; /* current port configuration */ + bfa_boolean_t use_flash_cfg; /* get port cfg from flash */ struct bfa_qos_attr_s qos_attr; /* QoS Attributes */ struct bfa_qos_vc_attr_s qos_vc_attr; /* VC info from ELP */ struct bfa_reqq_wait_s reqq_wait; diff --git a/drivers/scsi/bfa/bfi_ms.h b/drivers/scsi/bfa/bfi_ms.h index e0e5318ce007..8f22ef1a6ed9 100644 --- a/drivers/scsi/bfa/bfi_ms.h +++ b/drivers/scsi/bfa/bfi_ms.h @@ -188,7 +188,8 @@ struct bfi_fcport_rsp_s { struct bfi_mhdr_s mh; /* common msg header */ u8 status; /* port enable status */ u8 rsvd[3]; - u32 msgtag; /* msgtag for reply */ + struct bfa_port_cfg_s port_cfg;/* port configuration */ + u32 msgtag; /* msgtag for reply */ }; /* @@ -202,7 +203,8 @@ struct bfi_fcport_enable_req_s { struct bfa_port_cfg_s port_cfg; /* port configuration */ union bfi_addr_u stats_dma_addr; /* DMA address for stats */ u32 msgtag; /* msgtag for reply */ - u32 rsvd2; + u8 use_flash_cfg; /* get prot cfg from flash */ + u8 rsvd2[3]; }; /* -- cgit v1.2.3-59-g8ed1b From f1d584d70f31f54e0a559049906f42db89e2746d Mon Sep 17 00:00:00 2001 From: Krishna Gudipati Date: Mon, 13 Dec 2010 16:17:11 -0800 Subject: [SCSI] bfa: IOC auto recovery fix. - Made IOC auto_recovery synchronized and not timer based. - Only one PCI function will attempt to recover and reinitialize the ASIC on a failure, after all the active PCI fns acknowledge the IOC failure. Signed-off-by: Krishna Gudipati Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_ioc.c | 288 +++++++++++++++++++++++++++++++----------- drivers/scsi/bfa/bfa_ioc.h | 19 ++- drivers/scsi/bfa/bfa_ioc_cb.c | 95 +++++++++++++- drivers/scsi/bfa/bfa_ioc_ct.c | 101 ++++++++++++++- drivers/scsi/bfa/bfi_cbreg.h | 1 + drivers/scsi/bfa/bfi_ctreg.h | 41 +++--- 6 files changed, 445 insertions(+), 100 deletions(-) diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index 9173bf20ffba..05b0ff93284a 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -29,7 +29,7 @@ BFA_TRC_FILE(CNA, IOC); #define BFA_IOC_TOV 3000 /* msecs */ #define BFA_IOC_HWSEM_TOV 500 /* msecs */ #define BFA_IOC_HB_TOV 500 /* msecs */ -#define BFA_IOC_HWINIT_MAX 2 +#define BFA_IOC_HWINIT_MAX 5 #define BFA_IOC_TOV_RECOVER BFA_IOC_HB_TOV #define bfa_ioc_timer_start(__ioc) \ @@ -54,17 +54,16 @@ BFA_TRC_FILE(CNA, IOC); ((__ioc)->ioc_hwif->ioc_firmware_unlock(__ioc)) #define bfa_ioc_reg_init(__ioc) ((__ioc)->ioc_hwif->ioc_reg_init(__ioc)) #define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc)) -#define bfa_ioc_notify_hbfail(__ioc) \ - ((__ioc)->ioc_hwif->ioc_notify_hbfail(__ioc)) - -#ifdef BFA_IOC_IS_UEFI -#define bfa_ioc_is_bios_optrom(__ioc) (0) -#define bfa_ioc_is_uefi(__ioc) BFA_IOC_IS_UEFI -#else -#define bfa_ioc_is_bios_optrom(__ioc) \ - (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(__ioc)) < BFA_IOC_FWIMG_MINSZ) -#define bfa_ioc_is_uefi(__ioc) (0) -#endif +#define bfa_ioc_notify_fail(__ioc) \ + ((__ioc)->ioc_hwif->ioc_notify_fail(__ioc)) +#define bfa_ioc_sync_join(__ioc) \ + ((__ioc)->ioc_hwif->ioc_sync_join(__ioc)) +#define bfa_ioc_sync_leave(__ioc) \ + ((__ioc)->ioc_hwif->ioc_sync_leave(__ioc)) +#define bfa_ioc_sync_ack(__ioc) \ + ((__ioc)->ioc_hwif->ioc_sync_ack(__ioc)) +#define bfa_ioc_sync_complete(__ioc) \ + ((__ioc)->ioc_hwif->ioc_sync_complete(__ioc)) #define bfa_ioc_mbox_cmd_pending(__ioc) \ (!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \ @@ -104,10 +103,11 @@ enum ioc_event { IOC_E_ENABLED = 5, /* f/w enabled */ IOC_E_FWRSP_GETATTR = 6, /* IOC get attribute response */ IOC_E_DISABLED = 7, /* f/w disabled */ - IOC_E_PFFAILED = 8, /* failure notice by iocpf sm */ - IOC_E_HBFAIL = 9, /* heartbeat failure */ - IOC_E_HWERROR = 10, /* hardware error interrupt */ - IOC_E_TIMEOUT = 11, /* timeout */ + IOC_E_INITFAILED = 8, /* failure notice by iocpf sm */ + IOC_E_PFFAILED = 9, /* failure notice by iocpf sm */ + IOC_E_HBFAIL = 10, /* heartbeat failure */ + IOC_E_HWERROR = 11, /* hardware error interrupt */ + IOC_E_TIMEOUT = 12, /* timeout */ }; bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc_s, enum ioc_event); @@ -195,9 +195,14 @@ bfa_fsm_state_decl(bfa_iocpf, semwait, struct bfa_iocpf_s, enum iocpf_event); bfa_fsm_state_decl(bfa_iocpf, hwinit, struct bfa_iocpf_s, enum iocpf_event); bfa_fsm_state_decl(bfa_iocpf, enabling, struct bfa_iocpf_s, enum iocpf_event); bfa_fsm_state_decl(bfa_iocpf, ready, struct bfa_iocpf_s, enum iocpf_event); +bfa_fsm_state_decl(bfa_iocpf, initfail_sync, struct bfa_iocpf_s, + enum iocpf_event); bfa_fsm_state_decl(bfa_iocpf, initfail, struct bfa_iocpf_s, enum iocpf_event); +bfa_fsm_state_decl(bfa_iocpf, fail_sync, struct bfa_iocpf_s, enum iocpf_event); bfa_fsm_state_decl(bfa_iocpf, fail, struct bfa_iocpf_s, enum iocpf_event); bfa_fsm_state_decl(bfa_iocpf, disabling, struct bfa_iocpf_s, enum iocpf_event); +bfa_fsm_state_decl(bfa_iocpf, disabling_sync, struct bfa_iocpf_s, + enum iocpf_event); bfa_fsm_state_decl(bfa_iocpf, disabled, struct bfa_iocpf_s, enum iocpf_event); static struct bfa_sm_table_s iocpf_sm_table[] = { @@ -208,9 +213,12 @@ static struct bfa_sm_table_s iocpf_sm_table[] = { {BFA_SM(bfa_iocpf_sm_hwinit), BFA_IOCPF_HWINIT}, {BFA_SM(bfa_iocpf_sm_enabling), BFA_IOCPF_HWINIT}, {BFA_SM(bfa_iocpf_sm_ready), BFA_IOCPF_READY}, + {BFA_SM(bfa_iocpf_sm_initfail_sync), BFA_IOCPF_INITFAIL}, {BFA_SM(bfa_iocpf_sm_initfail), BFA_IOCPF_INITFAIL}, + {BFA_SM(bfa_iocpf_sm_fail_sync), BFA_IOCPF_FAIL}, {BFA_SM(bfa_iocpf_sm_fail), BFA_IOCPF_FAIL}, {BFA_SM(bfa_iocpf_sm_disabling), BFA_IOCPF_DISABLING}, + {BFA_SM(bfa_iocpf_sm_disabling_sync), BFA_IOCPF_DISABLING}, {BFA_SM(bfa_iocpf_sm_disabled), BFA_IOCPF_DISABLED}, }; @@ -497,7 +505,7 @@ bfa_ioc_sm_fail_retry_entry(struct bfa_ioc_s *ioc) } /* - * Hardware initialization failed. + * Hardware initialization retry. */ static void bfa_ioc_sm_fail_retry(struct bfa_ioc_s *ioc, enum ioc_event event) @@ -519,6 +527,10 @@ bfa_ioc_sm_fail_retry(struct bfa_ioc_s *ioc, enum ioc_event event) bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL); break; + case IOC_E_INITFAILED: + bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); + break; + case IOC_E_ENABLE: break; @@ -561,6 +573,11 @@ bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event) bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling); break; + case IOC_E_DETACH: + bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit); + bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP); + break; + case IOC_E_HWERROR: /* * HB failure notification, ignore. @@ -630,8 +647,15 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf_s *iocpf, enum iocpf_event event) switch (event) { case IOCPF_E_SEMLOCKED: if (bfa_ioc_firmware_lock(ioc)) { - iocpf->retry_count = 0; - bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); + if (bfa_ioc_sync_complete(ioc)) { + iocpf->retry_count = 0; + bfa_ioc_sync_join(ioc); + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); + } else { + bfa_ioc_firmware_unlock(ioc); + writel(1, ioc->ioc_regs.ioc_sem_reg); + bfa_sem_timer_start(ioc); + } } else { writel(1, ioc->ioc_regs.ioc_sem_reg); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_mismatch); @@ -722,13 +746,18 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf_s *iocpf, enum iocpf_event event) switch (event) { case IOCPF_E_SEMLOCKED: - iocpf->retry_count = 0; - bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); + if (bfa_ioc_sync_complete(ioc)) { + bfa_ioc_sync_join(ioc); + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); + } else { + writel(1, ioc->ioc_regs.ioc_sem_reg); + bfa_sem_timer_start(ioc); + } break; case IOCPF_E_DISABLE: bfa_sem_timer_stop(ioc); - bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync); break; default: @@ -767,23 +796,16 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event) */ case IOCPF_E_TIMEOUT: - iocpf->retry_count++; - if (iocpf->retry_count < BFA_IOC_HWINIT_MAX) { - bfa_iocpf_timer_start(ioc); - bfa_ioc_hwinit(ioc, BFA_TRUE); - break; - } - writel(1, ioc->ioc_regs.ioc_sem_reg); - bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); - if (event == IOCPF_E_TIMEOUT) bfa_fsm_send_event(ioc, IOC_E_PFFAILED); + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync); break; case IOCPF_E_DISABLE: - writel(1, ioc->ioc_regs.ioc_sem_reg); bfa_iocpf_timer_stop(ioc); + bfa_ioc_sync_leave(ioc); + writel(1, ioc->ioc_regs.ioc_sem_reg); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); break; @@ -824,18 +846,10 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event) */ case IOCPF_E_TIMEOUT: - iocpf->retry_count++; - if (iocpf->retry_count < BFA_IOC_HWINIT_MAX) { - writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate); - bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); - break; - } - writel(1, ioc->ioc_regs.ioc_sem_reg); - bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); - if (event == IOCPF_E_TIMEOUT) bfa_fsm_send_event(ioc, IOC_E_PFFAILED); + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync); break; case IOCPF_E_DISABLE: @@ -872,20 +886,21 @@ bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event) break; case IOCPF_E_GETATTRFAIL: - bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync); break; case IOCPF_E_FAIL: - bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync); break; case IOCPF_E_FWREADY: - if (bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op)) - bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); - else - bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); - - bfa_fsm_send_event(ioc, IOC_E_PFFAILED); + if (bfa_ioc_is_operational(ioc)) { + bfa_fsm_send_event(ioc, IOC_E_PFFAILED); + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync); + } else { + bfa_fsm_send_event(ioc, IOC_E_PFFAILED); + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync); + } break; default: @@ -914,7 +929,7 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event) case IOCPF_E_FWRSP_DISABLE: case IOCPF_E_FWREADY: bfa_iocpf_timer_stop(ioc); - bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync); break; case IOCPF_E_FAIL: @@ -925,7 +940,7 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event) case IOCPF_E_TIMEOUT: writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate); - bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync); break; case IOCPF_E_FWRSP_ENABLE: @@ -936,6 +951,37 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event) } } +static void +bfa_iocpf_sm_disabling_sync_entry(struct bfa_iocpf_s *iocpf) +{ + bfa_ioc_hw_sem_get(iocpf->ioc); +} + +/** + * IOC hb ack request is being removed. + */ +static void +bfa_iocpf_sm_disabling_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event) +{ + struct bfa_ioc_s *ioc = iocpf->ioc; + + bfa_trc(ioc, event); + + switch (event) { + case IOCPF_E_SEMLOCKED: + bfa_ioc_sync_leave(ioc); + writel(1, ioc->ioc_regs.ioc_sem_reg); + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); + break; + + case IOCPF_E_FAIL: + break; + + default: + bfa_sm_fault(ioc, event); + } +} + /* * IOC disable completion entry. */ @@ -954,6 +1000,7 @@ bfa_iocpf_sm_disabled(struct bfa_iocpf_s *iocpf, enum iocpf_event event) switch (event) { case IOCPF_E_ENABLE: + iocpf->retry_count = 0; bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait); break; @@ -967,10 +1014,65 @@ bfa_iocpf_sm_disabled(struct bfa_iocpf_s *iocpf, enum iocpf_event event) } } +static void +bfa_iocpf_sm_initfail_sync_entry(struct bfa_iocpf_s *iocpf) +{ + bfa_ioc_hw_sem_get(iocpf->ioc); +} + +/** + * @brief + * Hardware initialization failed. + */ +static void +bfa_iocpf_sm_initfail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event) +{ + struct bfa_ioc_s *ioc = iocpf->ioc; + + bfa_trc(ioc, event); + + switch (event) { + case IOCPF_E_SEMLOCKED: + bfa_ioc_notify_fail(ioc); + bfa_ioc_sync_ack(ioc); + iocpf->retry_count++; + if (iocpf->retry_count >= BFA_IOC_HWINIT_MAX) { + bfa_ioc_sync_leave(ioc); + writel(1, ioc->ioc_regs.ioc_sem_reg); + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); + } else { + if (bfa_ioc_sync_complete(ioc)) + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); + else { + writel(1, ioc->ioc_regs.ioc_sem_reg); + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait); + } + } + break; + + case IOCPF_E_DISABLE: + bfa_sem_timer_stop(ioc); + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync); + break; + + case IOCPF_E_STOP: + bfa_sem_timer_stop(ioc); + bfa_ioc_firmware_unlock(ioc); + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset); + break; + + case IOCPF_E_FAIL: + break; + + default: + bfa_sm_fault(ioc, event); + } +} + static void bfa_iocpf_sm_initfail_entry(struct bfa_iocpf_s *iocpf) { - bfa_iocpf_timer_start(iocpf->ioc); + bfa_fsm_send_event(iocpf->ioc, IOC_E_INITFAILED); } /* @@ -985,46 +1087,77 @@ bfa_iocpf_sm_initfail(struct bfa_iocpf_s *iocpf, enum iocpf_event event) switch (event) { case IOCPF_E_DISABLE: - bfa_iocpf_timer_stop(ioc); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); break; case IOCPF_E_STOP: - bfa_iocpf_timer_stop(ioc); bfa_ioc_firmware_unlock(ioc); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset); break; - case IOCPF_E_TIMEOUT: - bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait); - break; - default: bfa_sm_fault(ioc, event); } } static void -bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf) +bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf_s *iocpf) { - /* + /** * Mark IOC as failed in hardware and stop firmware. */ bfa_ioc_lpu_stop(iocpf->ioc); - writel(BFI_IOC_FAIL, iocpf->ioc->ioc_regs.ioc_fwstate); - - /* - * Notify other functions on HB failure. - */ - bfa_ioc_notify_hbfail(iocpf->ioc); - /* + /** * Flush any queued up mailbox requests. */ bfa_ioc_mbox_hbfail(iocpf->ioc); - if (iocpf->auto_recover) - bfa_iocpf_recovery_timer_start(iocpf->ioc); + bfa_ioc_hw_sem_get(iocpf->ioc); +} + +static void +bfa_iocpf_sm_fail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event) +{ + struct bfa_ioc_s *ioc = iocpf->ioc; + + bfa_trc(ioc, event); + + switch (event) { + case IOCPF_E_SEMLOCKED: + iocpf->retry_count = 0; + bfa_ioc_sync_ack(ioc); + bfa_ioc_notify_fail(ioc); + if (!iocpf->auto_recover) { + bfa_ioc_sync_leave(ioc); + writel(1, ioc->ioc_regs.ioc_sem_reg); + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); + } else { + if (bfa_ioc_sync_complete(ioc)) + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); + else { + writel(1, ioc->ioc_regs.ioc_sem_reg); + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait); + } + } + break; + + case IOCPF_E_DISABLE: + bfa_sem_timer_stop(ioc); + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync); + break; + + case IOCPF_E_FAIL: + break; + + default: + bfa_sm_fault(ioc, event); + } +} + +static void +bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf) +{ } /* @@ -1039,15 +1172,9 @@ bfa_iocpf_sm_fail(struct bfa_iocpf_s *iocpf, enum iocpf_event event) switch (event) { case IOCPF_E_DISABLE: - if (iocpf->auto_recover) - bfa_iocpf_timer_stop(ioc); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); break; - case IOCPF_E_TIMEOUT: - bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait); - break; - default: bfa_sm_fault(ioc, event); } @@ -1438,7 +1565,6 @@ bfa_ioc_hb_check(void *cbarg) hb_count = readl(ioc->ioc_regs.heartbeat); if (ioc->hb_count == hb_count) { - printk(KERN_CRIT "Firmware heartbeat failure at %d", hb_count); bfa_ioc_recover(ioc); return; } else { @@ -2153,6 +2279,16 @@ bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc) return BFA_TRUE; } +/** + * Reset IOC fwstate registers. + */ +void +bfa_ioc_reset_fwstate(struct bfa_ioc_s *ioc) +{ + writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate); + writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate); +} + #define BFA_MFG_NAME "Brocade" void bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc, diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index 62153f283216..5d2f34290e9d 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h @@ -149,8 +149,11 @@ struct bfa_ioc_regs_s { void __iomem *host_page_num_fn; void __iomem *heartbeat; void __iomem *ioc_fwstate; + void __iomem *alt_ioc_fwstate; void __iomem *ll_halt; + void __iomem *alt_ll_halt; void __iomem *err_set; + void __iomem *ioc_fail_sync; void __iomem *shirq_isr_next; void __iomem *shirq_msk_next; void __iomem *smem_page_start; @@ -258,8 +261,12 @@ struct bfa_ioc_hwif_s { void (*ioc_map_port) (struct bfa_ioc_s *ioc); void (*ioc_isr_mode_set) (struct bfa_ioc_s *ioc, bfa_boolean_t msix); - void (*ioc_notify_hbfail) (struct bfa_ioc_s *ioc); + void (*ioc_notify_fail) (struct bfa_ioc_s *ioc); void (*ioc_ownership_reset) (struct bfa_ioc_s *ioc); + void (*ioc_sync_join) (struct bfa_ioc_s *ioc); + void (*ioc_sync_leave) (struct bfa_ioc_s *ioc); + void (*ioc_sync_ack) (struct bfa_ioc_s *ioc); + bfa_boolean_t (*ioc_sync_complete) (struct bfa_ioc_s *ioc); }; #define bfa_ioc_pcifn(__ioc) ((__ioc)->pcidev.pci_func) @@ -289,6 +296,15 @@ struct bfa_ioc_hwif_s { #define BFA_IOC_FLASH_OFFSET_IN_CHUNK(off) (off % BFI_FLASH_CHUNK_SZ_WORDS) #define BFA_IOC_FLASH_CHUNK_ADDR(chunkno) (chunkno * BFI_FLASH_CHUNK_SZ_WORDS) +#ifdef BFA_IOC_IS_UEFI +#define bfa_ioc_is_bios_optrom(__ioc) (0) +#define bfa_ioc_is_uefi(__ioc) BFA_IOC_IS_UEFI +#else +#define bfa_ioc_is_bios_optrom(__ioc) \ + (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(__ioc)) < BFA_IOC_FWIMG_MINSZ) +#define bfa_ioc_is_uefi(__ioc) (0) +#endif + /* * IOC mailbox interface */ @@ -343,6 +359,7 @@ bfa_boolean_t bfa_ioc_is_initialized(struct bfa_ioc_s *ioc); bfa_boolean_t bfa_ioc_is_disabled(struct bfa_ioc_s *ioc); bfa_boolean_t bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc); bfa_boolean_t bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc); +void bfa_ioc_reset_fwstate(struct bfa_ioc_s *ioc); enum bfa_ioc_type_e bfa_ioc_get_type(struct bfa_ioc_s *ioc); void bfa_ioc_get_adapter_serial_num(struct bfa_ioc_s *ioc, char *serial_num); void bfa_ioc_get_adapter_fw_ver(struct bfa_ioc_s *ioc, char *fw_ver); diff --git a/drivers/scsi/bfa/bfa_ioc_cb.c b/drivers/scsi/bfa/bfa_ioc_cb.c index a0e05da9df51..788ecca5aa01 100644 --- a/drivers/scsi/bfa/bfa_ioc_cb.c +++ b/drivers/scsi/bfa/bfa_ioc_cb.c @@ -30,8 +30,12 @@ static void bfa_ioc_cb_firmware_unlock(struct bfa_ioc_s *ioc); static void bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc); static void bfa_ioc_cb_map_port(struct bfa_ioc_s *ioc); static void bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix); -static void bfa_ioc_cb_notify_hbfail(struct bfa_ioc_s *ioc); +static void bfa_ioc_cb_notify_fail(struct bfa_ioc_s *ioc); static void bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc); +static void bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc); +static void bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc); +static void bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc); +static bfa_boolean_t bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc); static struct bfa_ioc_hwif_s hwif_cb; @@ -47,18 +51,38 @@ bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc) hwif_cb.ioc_reg_init = bfa_ioc_cb_reg_init; hwif_cb.ioc_map_port = bfa_ioc_cb_map_port; hwif_cb.ioc_isr_mode_set = bfa_ioc_cb_isr_mode_set; - hwif_cb.ioc_notify_hbfail = bfa_ioc_cb_notify_hbfail; + hwif_cb.ioc_notify_fail = bfa_ioc_cb_notify_fail; hwif_cb.ioc_ownership_reset = bfa_ioc_cb_ownership_reset; + hwif_cb.ioc_sync_join = bfa_ioc_cb_sync_join; + hwif_cb.ioc_sync_leave = bfa_ioc_cb_sync_leave; + hwif_cb.ioc_sync_ack = bfa_ioc_cb_sync_ack; + hwif_cb.ioc_sync_complete = bfa_ioc_cb_sync_complete; ioc->ioc_hwif = &hwif_cb; } -/* +/** * Return true if firmware of current driver matches the running firmware. */ static bfa_boolean_t bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc) { + struct bfi_ioc_image_hdr_s fwhdr; + uint32_t fwstate = readl(ioc->ioc_regs.ioc_fwstate); + + if ((fwstate == BFI_IOC_UNINIT) || bfa_ioc_is_uefi(ioc) || + bfa_ioc_is_bios_optrom(ioc)) + return BFA_TRUE; + + bfa_ioc_fwver_get(ioc, &fwhdr); + + if (swab32(fwhdr.exec) == BFI_BOOT_TYPE_NORMAL) + return BFA_TRUE; + + bfa_trc(ioc, fwstate); + bfa_trc(ioc, fwhdr.exec); + writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate); + return BFA_TRUE; } @@ -71,7 +95,7 @@ bfa_ioc_cb_firmware_unlock(struct bfa_ioc_s *ioc) * Notify other functions on HB failure. */ static void -bfa_ioc_cb_notify_hbfail(struct bfa_ioc_s *ioc) +bfa_ioc_cb_notify_fail(struct bfa_ioc_s *ioc) { writel(__PSS_ERR_STATUS_SET, ioc->ioc_regs.err_set); readl(ioc->ioc_regs.err_set); @@ -109,9 +133,11 @@ bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc) if (ioc->port_id == 0) { ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG; ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG; + ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC1_STATE_REG; } else { ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG); ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG); + ioc->ioc_regs.alt_ioc_fwstate = (rb + BFA_IOC0_STATE_REG); } /* @@ -185,7 +211,68 @@ bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc) writel(1, ioc->ioc_regs.ioc_sem_reg); } +/** + * Synchronized IOC failure processing routines + */ +static void +bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc) +{ +} +static void +bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc) +{ +} + +static void +bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc) +{ + writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate); +} + +static bfa_boolean_t +bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc) +{ + uint32_t fwstate, alt_fwstate; + fwstate = readl(ioc->ioc_regs.ioc_fwstate); + + /** + * At this point, this IOC is hoding the hw sem in the + * start path (fwcheck) OR in the disable/enable path + * OR to check if the other IOC has acknowledged failure. + * + * So, this IOC can be in UNINIT, INITING, DISABLED, FAIL + * or in MEMTEST states. In a normal scenario, this IOC + * can not be in OP state when this function is called. + * + * However, this IOC could still be in OP state when + * the OS driver is starting up, if the OptROM code has + * left it in that state. + * + * If we had marked this IOC's fwstate as BFI_IOC_FAIL + * in the failure case and now, if the fwstate is not + * BFI_IOC_FAIL it implies that the other PCI fn have + * reinitialized the ASIC or this IOC got disabled, so + * return TRUE. + */ + if (fwstate == BFI_IOC_UNINIT || + fwstate == BFI_IOC_INITING || + fwstate == BFI_IOC_DISABLED || + fwstate == BFI_IOC_MEMTEST || + fwstate == BFI_IOC_OP) + return BFA_TRUE; + else { + alt_fwstate = readl(ioc->ioc_regs.alt_ioc_fwstate); + if (alt_fwstate == BFI_IOC_FAIL || + alt_fwstate == BFI_IOC_DISABLED || + alt_fwstate == BFI_IOC_UNINIT || + alt_fwstate == BFI_IOC_INITING || + alt_fwstate == BFI_IOC_MEMTEST) + return BFA_TRUE; + else + return BFA_FALSE; + } +} bfa_status_t bfa_ioc_cb_pll_init(void __iomem *rb, bfa_boolean_t fcmode) diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c index 25a5d3c339c8..9da55a836bfb 100644 --- a/drivers/scsi/bfa/bfa_ioc_ct.c +++ b/drivers/scsi/bfa/bfa_ioc_ct.c @@ -22,6 +22,15 @@ BFA_TRC_FILE(CNA, IOC_CT); +#define bfa_ioc_ct_sync_pos(__ioc) \ + ((uint32_t) (1 << bfa_ioc_pcifn(__ioc))) +#define BFA_IOC_SYNC_REQD_SH 16 +#define bfa_ioc_ct_get_sync_ackd(__val) (__val & 0x0000ffff) +#define bfa_ioc_ct_clear_sync_ackd(__val) (__val & 0xffff0000) +#define bfa_ioc_ct_get_sync_reqd(__val) (__val >> BFA_IOC_SYNC_REQD_SH) +#define bfa_ioc_ct_sync_reqd_pos(__ioc) \ + (bfa_ioc_ct_sync_pos(__ioc) << BFA_IOC_SYNC_REQD_SH) + /* * forward declarations */ @@ -30,8 +39,12 @@ static void bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc); static void bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc); static void bfa_ioc_ct_map_port(struct bfa_ioc_s *ioc); static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix); -static void bfa_ioc_ct_notify_hbfail(struct bfa_ioc_s *ioc); +static void bfa_ioc_ct_notify_fail(struct bfa_ioc_s *ioc); static void bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc); +static void bfa_ioc_ct_sync_join(struct bfa_ioc_s *ioc); +static void bfa_ioc_ct_sync_leave(struct bfa_ioc_s *ioc); +static void bfa_ioc_ct_sync_ack(struct bfa_ioc_s *ioc); +static bfa_boolean_t bfa_ioc_ct_sync_complete(struct bfa_ioc_s *ioc); static struct bfa_ioc_hwif_s hwif_ct; @@ -47,8 +60,12 @@ bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc) hwif_ct.ioc_reg_init = bfa_ioc_ct_reg_init; hwif_ct.ioc_map_port = bfa_ioc_ct_map_port; hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set; - hwif_ct.ioc_notify_hbfail = bfa_ioc_ct_notify_hbfail; + hwif_ct.ioc_notify_fail = bfa_ioc_ct_notify_fail; hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset; + hwif_ct.ioc_sync_join = bfa_ioc_ct_sync_join; + hwif_ct.ioc_sync_leave = bfa_ioc_ct_sync_leave; + hwif_ct.ioc_sync_ack = bfa_ioc_ct_sync_ack; + hwif_ct.ioc_sync_complete = bfa_ioc_ct_sync_complete; ioc->ioc_hwif = &hwif_ct; } @@ -85,6 +102,7 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc) if (usecnt == 0) { writel(1, ioc->ioc_regs.ioc_usage_reg); writel(1, ioc->ioc_regs.ioc_usage_sem_reg); + writel(0, ioc->ioc_regs.ioc_fail_sync); bfa_trc(ioc, usecnt); return BFA_TRUE; } @@ -153,12 +171,14 @@ bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc) * Notify other functions on HB failure. */ static void -bfa_ioc_ct_notify_hbfail(struct bfa_ioc_s *ioc) +bfa_ioc_ct_notify_fail(struct bfa_ioc_s *ioc) { if (ioc->cna) { writel(__FW_INIT_HALT_P, ioc->ioc_regs.ll_halt); + writel(__FW_INIT_HALT_P, ioc->ioc_regs.alt_ll_halt); /* Wait for halt to take effect */ readl(ioc->ioc_regs.ll_halt); + readl(ioc->ioc_regs.alt_ll_halt); } else { writel(__PSS_ERR_STATUS_SET, ioc->ioc_regs.err_set); readl(ioc->ioc_regs.err_set); @@ -210,15 +230,19 @@ bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc) if (ioc->port_id == 0) { ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG; ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG; + ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC1_STATE_REG; ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].hfn; ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].lpu; ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0; + ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P1; } else { ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG); ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG); + ioc->ioc_regs.alt_ioc_fwstate = rb + BFA_IOC0_STATE_REG; ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].hfn; ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].lpu; ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1; + ioc->ioc_regs.alt_ll_halt = rb + FW_INIT_HALT_P0; } /* @@ -236,6 +260,7 @@ bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc) ioc->ioc_regs.ioc_usage_sem_reg = (rb + HOST_SEM1_REG); ioc->ioc_regs.ioc_init_sem_reg = (rb + HOST_SEM2_REG); ioc->ioc_regs.ioc_usage_reg = (rb + BFA_FW_USE_COUNT); + ioc->ioc_regs.ioc_fail_sync = (rb + BFA_IOC_FAIL_SYNC); /* * sram memory access @@ -326,7 +351,77 @@ bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc) writel(1, ioc->ioc_regs.ioc_sem_reg); } +/** + * Synchronized IOC failure processing routines + */ +static void +bfa_ioc_ct_sync_join(struct bfa_ioc_s *ioc) +{ + uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync); + uint32_t sync_pos = bfa_ioc_ct_sync_reqd_pos(ioc); + + writel((r32 | sync_pos), ioc->ioc_regs.ioc_fail_sync); +} +static void +bfa_ioc_ct_sync_leave(struct bfa_ioc_s *ioc) +{ + uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync); + uint32_t sync_msk = bfa_ioc_ct_sync_reqd_pos(ioc) | + bfa_ioc_ct_sync_pos(ioc); + + writel((r32 & ~sync_msk), ioc->ioc_regs.ioc_fail_sync); +} + +static void +bfa_ioc_ct_sync_ack(struct bfa_ioc_s *ioc) +{ + uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync); + + writel((r32 | bfa_ioc_ct_sync_pos(ioc)), + ioc->ioc_regs.ioc_fail_sync); +} + +static bfa_boolean_t +bfa_ioc_ct_sync_complete(struct bfa_ioc_s *ioc) +{ + uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync); + uint32_t sync_reqd = bfa_ioc_ct_get_sync_reqd(r32); + uint32_t sync_ackd = bfa_ioc_ct_get_sync_ackd(r32); + uint32_t tmp_ackd; + + if (sync_ackd == 0) + return BFA_TRUE; + + /** + * The check below is to see whether any other PCI fn + * has reinitialized the ASIC (reset sync_ackd bits) + * and failed again while this IOC was waiting for hw + * semaphore (in bfa_iocpf_sm_semwait()). + */ + tmp_ackd = sync_ackd; + if ((sync_reqd & bfa_ioc_ct_sync_pos(ioc)) && + !(sync_ackd & bfa_ioc_ct_sync_pos(ioc))) + sync_ackd |= bfa_ioc_ct_sync_pos(ioc); + + if (sync_reqd == sync_ackd) { + writel(bfa_ioc_ct_clear_sync_ackd(r32), + ioc->ioc_regs.ioc_fail_sync); + writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate); + writel(BFI_IOC_FAIL, ioc->ioc_regs.alt_ioc_fwstate); + return BFA_TRUE; + } + + /** + * If another PCI fn reinitialized and failed again while + * this IOC was waiting for hw sem, the sync_ackd bit for + * this IOC need to be set again to allow reinitialization. + */ + if (tmp_ackd != sync_ackd) + writel((r32 | sync_ackd), ioc->ioc_regs.ioc_fail_sync); + + return BFA_FALSE; +} /* * Check the firmware state to know if pll_init has been completed already diff --git a/drivers/scsi/bfa/bfi_cbreg.h b/drivers/scsi/bfa/bfi_cbreg.h index 6f03ed382c69..39ad42b66b5b 100644 --- a/drivers/scsi/bfa/bfi_cbreg.h +++ b/drivers/scsi/bfa/bfi_cbreg.h @@ -208,6 +208,7 @@ #define BFA_IOC1_HBEAT_REG HOST_SEM2_INFO_REG #define BFA_IOC1_STATE_REG HOST_SEM3_INFO_REG #define BFA_FW_USE_COUNT HOST_SEM4_INFO_REG +#define BFA_IOC_FAIL_SYNC HOST_SEM5_INFO_REG #define CPE_Q_DEPTH(__n) \ (CPE_Q0_DEPTH + (__n) * (CPE_Q1_DEPTH - CPE_Q0_DEPTH)) diff --git a/drivers/scsi/bfa/bfi_ctreg.h b/drivers/scsi/bfa/bfi_ctreg.h index 62b86a4b0e4b..fc4ce4a5a183 100644 --- a/drivers/scsi/bfa/bfi_ctreg.h +++ b/drivers/scsi/bfa/bfi_ctreg.h @@ -522,6 +522,7 @@ enum { #define BFA_IOC1_HBEAT_REG HOST_SEM2_INFO_REG #define BFA_IOC1_STATE_REG HOST_SEM3_INFO_REG #define BFA_FW_USE_COUNT HOST_SEM4_INFO_REG +#define BFA_IOC_FAIL_SYNC HOST_SEM5_INFO_REG #define CPE_DEPTH_Q(__n) \ (CPE_DEPTH_Q0 + (__n) * (CPE_DEPTH_Q1 - CPE_DEPTH_Q0)) @@ -539,22 +540,30 @@ enum { (RME_PI_PTR_Q0 + (__n) * (RME_PI_PTR_Q1 - RME_PI_PTR_Q0)) #define RME_CI_PTR_Q(__n) \ (RME_CI_PTR_Q0 + (__n) * (RME_CI_PTR_Q1 - RME_CI_PTR_Q0)) -#define HQM_QSET_RXQ_DRBL_P0(__n) (HQM_QSET0_RXQ_DRBL_P0 + (__n) \ - * (HQM_QSET1_RXQ_DRBL_P0 - HQM_QSET0_RXQ_DRBL_P0)) -#define HQM_QSET_TXQ_DRBL_P0(__n) (HQM_QSET0_TXQ_DRBL_P0 + (__n) \ - * (HQM_QSET1_TXQ_DRBL_P0 - HQM_QSET0_TXQ_DRBL_P0)) -#define HQM_QSET_IB_DRBL_1_P0(__n) (HQM_QSET0_IB_DRBL_1_P0 + (__n) \ - * (HQM_QSET1_IB_DRBL_1_P0 - HQM_QSET0_IB_DRBL_1_P0)) -#define HQM_QSET_IB_DRBL_2_P0(__n) (HQM_QSET0_IB_DRBL_2_P0 + (__n) \ - * (HQM_QSET1_IB_DRBL_2_P0 - HQM_QSET0_IB_DRBL_2_P0)) -#define HQM_QSET_RXQ_DRBL_P1(__n) (HQM_QSET0_RXQ_DRBL_P1 + (__n) \ - * (HQM_QSET1_RXQ_DRBL_P1 - HQM_QSET0_RXQ_DRBL_P1)) -#define HQM_QSET_TXQ_DRBL_P1(__n) (HQM_QSET0_TXQ_DRBL_P1 + (__n) \ - * (HQM_QSET1_TXQ_DRBL_P1 - HQM_QSET0_TXQ_DRBL_P1)) -#define HQM_QSET_IB_DRBL_1_P1(__n) (HQM_QSET0_IB_DRBL_1_P1 + (__n) \ - * (HQM_QSET1_IB_DRBL_1_P1 - HQM_QSET0_IB_DRBL_1_P1)) -#define HQM_QSET_IB_DRBL_2_P1(__n) (HQM_QSET0_IB_DRBL_2_P1 + (__n) \ - * (HQM_QSET1_IB_DRBL_2_P1 - HQM_QSET0_IB_DRBL_2_P1)) +#define HQM_QSET_RXQ_DRBL_P0(__n) \ + (HQM_QSET0_RXQ_DRBL_P0 + (__n) * \ + (HQM_QSET1_RXQ_DRBL_P0 - HQM_QSET0_RXQ_DRBL_P0)) +#define HQM_QSET_TXQ_DRBL_P0(__n) \ + (HQM_QSET0_TXQ_DRBL_P0 + (__n) * \ + (HQM_QSET1_TXQ_DRBL_P0 - HQM_QSET0_TXQ_DRBL_P0)) +#define HQM_QSET_IB_DRBL_1_P0(__n) \ + (HQM_QSET0_IB_DRBL_1_P0 + (__n) * \ + (HQM_QSET1_IB_DRBL_1_P0 - HQM_QSET0_IB_DRBL_1_P0)) +#define HQM_QSET_IB_DRBL_2_P0(__n) \ + (HQM_QSET0_IB_DRBL_2_P0 + (__n) * \ + (HQM_QSET1_IB_DRBL_2_P0 - HQM_QSET0_IB_DRBL_2_P0)) +#define HQM_QSET_RXQ_DRBL_P1(__n) \ + (HQM_QSET0_RXQ_DRBL_P1 + (__n) * \ + (HQM_QSET1_RXQ_DRBL_P1 - HQM_QSET0_RXQ_DRBL_P1)) +#define HQM_QSET_TXQ_DRBL_P1(__n) \ + (HQM_QSET0_TXQ_DRBL_P1 + (__n) * \ + (HQM_QSET1_TXQ_DRBL_P1 - HQM_QSET0_TXQ_DRBL_P1)) +#define HQM_QSET_IB_DRBL_1_P1(__n) \ + (HQM_QSET0_IB_DRBL_1_P1 + (__n) * \ + (HQM_QSET1_IB_DRBL_1_P1 - HQM_QSET0_IB_DRBL_1_P1)) +#define HQM_QSET_IB_DRBL_2_P1(__n) \ + (HQM_QSET0_IB_DRBL_2_P1 + (__n) * \ + (HQM_QSET1_IB_DRBL_2_P1 - HQM_QSET0_IB_DRBL_2_P1)) #define CPE_Q_NUM(__fn, __q) (((__fn) << 2) + (__q)) #define RME_Q_NUM(__fn, __q) (((__fn) << 2) + (__q)) -- cgit v1.2.3-59-g8ed1b From b704495c6707013806d1b66507a967896e2b4a7c Mon Sep 17 00:00:00 2001 From: Krishna Gudipati Date: Mon, 13 Dec 2010 16:17:42 -0800 Subject: [SCSI] bfa: direct attach mode fix. - Direct attach is not working due to the check of PID in fcxp_send request. - Added logic to set the lps->lp_pid with the PID assigned for n2n mode. Signed-off-by: Krishna Gudipati Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_fcs.h | 1 + drivers/scsi/bfa/bfa_fcs_lport.c | 3 ++ drivers/scsi/bfa/bfa_svc.c | 99 +++++++++++++++++++++++++++++++++++++++- drivers/scsi/bfa/bfa_svc.h | 1 + drivers/scsi/bfa/bfi_ms.h | 8 ++++ 5 files changed, 111 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h index f0e652b50994..0fd63168573f 100644 --- a/drivers/scsi/bfa/bfa_fcs.h +++ b/drivers/scsi/bfa/bfa_fcs.h @@ -38,6 +38,7 @@ enum bfa_lps_event { BFA_LPS_SM_DELETE = 5, /* lps delete from user */ BFA_LPS_SM_OFFLINE = 6, /* Link is offline */ BFA_LPS_SM_RX_CVL = 7, /* Rx clear virtual link */ + BFA_LPS_SM_SET_N2N_PID = 8, /* Set assigned PID for n2n */ }; diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c index aa4516672eed..4f2e4e095d67 100644 --- a/drivers/scsi/bfa/bfa_fcs_lport.c +++ b/drivers/scsi/bfa/bfa_fcs_lport.c @@ -309,6 +309,7 @@ bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port, return; } port->pid = rx_fchs->d_id; + bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id); } /* @@ -323,6 +324,7 @@ bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port, (memcmp((void *)&bfa_fcs_lport_get_pwwn(port), (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) { port->pid = rx_fchs->d_id; + bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id); rport->pid = rx_fchs->s_id; } bfa_fcs_rport_plogi(rport, rx_fchs, plogi); @@ -979,6 +981,7 @@ bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port) ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn, sizeof(wwn_t)) > 0) { port->pid = N2N_LOCAL_PID; + bfa_lps_set_n2n_pid(port->fabric->lps, N2N_LOCAL_PID); /* * First, check if we know the device by pwwn. */ diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c index 2666472d1429..b7df5534da85 100644 --- a/drivers/scsi/bfa/bfa_svc.c +++ b/drivers/scsi/bfa/bfa_svc.c @@ -131,6 +131,7 @@ static void bfa_lps_reqq_resume(void *lps_arg); static void bfa_lps_free(struct bfa_lps_s *lps); static void bfa_lps_send_login(struct bfa_lps_s *lps); static void bfa_lps_send_logout(struct bfa_lps_s *lps); +static void bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps); static void bfa_lps_login_comp(struct bfa_lps_s *lps); static void bfa_lps_logout_comp(struct bfa_lps_s *lps); static void bfa_lps_cvl_event(struct bfa_lps_s *lps); @@ -143,6 +144,8 @@ static void bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event); static void bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event); static void bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event); +static void bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps, + enum bfa_lps_event event); static void bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event); static void bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event); @@ -1254,6 +1257,12 @@ bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event) else bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS, BFA_PL_EID_LOGIN, 0, "FLOGI Accept"); + /* If N2N, send the assigned PID to FW */ + bfa_trc(lps->bfa, lps->fport); + bfa_trc(lps->bfa, lps->lp_pid); + + if (!lps->fport && lps->lp_pid) + bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID); } else { bfa_sm_set_state(lps, bfa_lps_sm_init); if (lps->fdisc) @@ -1272,6 +1281,11 @@ bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event) bfa_sm_set_state(lps, bfa_lps_sm_init); break; + case BFA_LPS_SM_SET_N2N_PID: + bfa_trc(lps->bfa, lps->fport); + bfa_trc(lps->bfa, lps->lp_pid); + break; + default: bfa_sm_fault(lps->bfa, event); } @@ -1340,6 +1354,14 @@ bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event) BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx"); break; + case BFA_LPS_SM_SET_N2N_PID: + if (bfa_reqq_full(lps->bfa, lps->reqq)) { + bfa_sm_set_state(lps, bfa_lps_sm_online_n2n_pid_wait); + bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe); + } else + bfa_lps_send_set_n2n_pid(lps); + break; + case BFA_LPS_SM_OFFLINE: case BFA_LPS_SM_DELETE: bfa_sm_set_state(lps, bfa_lps_sm_init); @@ -1350,6 +1372,48 @@ bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event) } } +/** + * login complete + */ +static void +bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps, enum bfa_lps_event event) +{ + bfa_trc(lps->bfa, lps->lp_tag); + bfa_trc(lps->bfa, event); + + switch (event) { + case BFA_LPS_SM_RESUME: + bfa_sm_set_state(lps, bfa_lps_sm_online); + bfa_lps_send_set_n2n_pid(lps); + break; + + case BFA_LPS_SM_LOGOUT: + bfa_sm_set_state(lps, bfa_lps_sm_logowait); + bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS, + BFA_PL_EID_LOGO, 0, "Logout"); + break; + + case BFA_LPS_SM_RX_CVL: + bfa_sm_set_state(lps, bfa_lps_sm_init); + bfa_reqq_wcancel(&lps->wqe); + + /* Let the vport module know about this event */ + bfa_lps_cvl_event(lps); + bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS, + BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx"); + break; + + case BFA_LPS_SM_OFFLINE: + case BFA_LPS_SM_DELETE: + bfa_sm_set_state(lps, bfa_lps_sm_init); + bfa_reqq_wcancel(&lps->wqe); + break; + + default: + bfa_sm_fault(lps->bfa, event); + } +} + /* * logout in progress - awaiting firmware response */ @@ -1498,8 +1562,9 @@ bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp) switch (rsp->status) { case BFA_STATUS_OK: lps->fport = rsp->f_port; + if (lps->fport) + lps->lp_pid = rsp->lp_pid; lps->npiv_en = rsp->npiv_en; - lps->lp_pid = rsp->lp_pid; lps->pr_bbcred = be16_to_cpu(rsp->bb_credit); lps->pr_pwwn = rsp->port_name; lps->pr_nwwn = rsp->node_name; @@ -1626,6 +1691,25 @@ bfa_lps_send_logout(struct bfa_lps_s *lps) bfa_reqq_produce(lps->bfa, lps->reqq); } +/** + * send n2n pid set request to firmware + */ +static void +bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps) +{ + struct bfi_lps_n2n_pid_req_s *m; + + m = bfa_reqq_next(lps->bfa, lps->reqq); + bfa_assert(m); + + bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_N2N_PID_REQ, + bfa_lpuid(lps->bfa)); + + m->lp_tag = lps->lp_tag; + m->lp_pid = lps->lp_pid; + bfa_reqq_produce(lps->bfa, lps->reqq); +} + /* * Indirect login completion handler for non-fcs */ @@ -1846,6 +1930,19 @@ bfa_lps_get_base_pid(struct bfa_s *bfa) return BFA_LPS_FROM_TAG(mod, 0)->lp_pid; } +/** + * Set PID in case of n2n (which is assigned during PLOGI) + */ +void +bfa_lps_set_n2n_pid(struct bfa_lps_s *lps, uint32_t n2n_pid) +{ + bfa_trc(lps->bfa, lps->lp_tag); + bfa_trc(lps->bfa, n2n_pid); + + lps->lp_pid = n2n_pid; + bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID); +} + /* * LPS firmware message class handler. */ diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h index 36c81c74f04a..331ad992a581 100644 --- a/drivers/scsi/bfa/bfa_svc.h +++ b/drivers/scsi/bfa/bfa_svc.h @@ -610,6 +610,7 @@ void bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, void bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn, wwn_t nwwn); void bfa_lps_fdisclogo(struct bfa_lps_s *lps); +void bfa_lps_set_n2n_pid(struct bfa_lps_s *lps, u32 n2n_pid); u32 bfa_lps_get_base_pid(struct bfa_s *bfa); u8 bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid); void bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status); diff --git a/drivers/scsi/bfa/bfi_ms.h b/drivers/scsi/bfa/bfi_ms.h index 8f22ef1a6ed9..19e888a57555 100644 --- a/drivers/scsi/bfa/bfi_ms.h +++ b/drivers/scsi/bfa/bfi_ms.h @@ -342,6 +342,7 @@ struct bfi_uf_frm_rcvd_s { enum bfi_lps_h2i_msgs { BFI_LPS_H2I_LOGIN_REQ = 1, BFI_LPS_H2I_LOGOUT_REQ = 2, + BFI_LPS_H2I_N2N_PID_REQ = 3, }; enum bfi_lps_i2h_msgs { @@ -401,10 +402,17 @@ struct bfi_lps_cvl_event_s { u8 rsvd[3]; }; +struct bfi_lps_n2n_pid_req_s { + struct bfi_mhdr_s mh; /* common msg header */ + u8 lp_tag; + u32 lp_pid:24; +}; + union bfi_lps_h2i_msg_u { struct bfi_mhdr_s *msg; struct bfi_lps_login_req_s *login_req; struct bfi_lps_logout_req_s *logout_req; + struct bfi_lps_n2n_pid_req_s *n2n_pid_req; }; union bfi_lps_i2h_msg_u { -- cgit v1.2.3-59-g8ed1b From 15821f05b78dbeb2f897d1d22576449103a4d8d5 Mon Sep 17 00:00:00 2001 From: Krishna Gudipati Date: Mon, 13 Dec 2010 16:23:27 -0800 Subject: [SCSI] bfa: io tag handling and minor bug fix. Fix iotag handling: 1) Update and check io tag for retry case. 2) Clearing upper 3 bits in io tag when an IO completes. The 3 upper bits in io tags are used for counting FCP exchange retry. Un-cleared bits will cause firmware to access invalid memory when the same io tag is used for an IO to a target that doesn't support FCP exchange retry. 3) Only check the effective bits when validating an iotag. Other minor fixes: 1) Added trace to get FC header type with assert of unhandled packet received. Ignore the type FC_TYPE_FC_FSS (FC_XS). 2) Fixed the adapter info display check - to check for fcmode flag even. Signed-off-by: Krishna Gudipati Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_fcpim.c | 8 +++++--- drivers/scsi/bfa/bfa_fcpim.h | 22 ++++++++++++---------- drivers/scsi/bfa/bfa_fcs_lport.c | 8 ++++++-- drivers/scsi/bfa/bfad_im.c | 2 +- 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c index 314c93122980..5e697f236ef3 100644 --- a/drivers/scsi/bfa/bfa_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcpim.c @@ -1540,8 +1540,8 @@ bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) break; case BFA_IOIM_SM_SQRETRY: - if (bfa_ioim_get_iotag(ioim) != BFA_TRUE) { - /* max retry completed free IO */ + if (bfa_ioim_maxretry_reached(ioim)) { + /* max retry reached, free IO */ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free); bfa_ioim_move_to_comp_q(ioim); bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, @@ -1569,6 +1569,7 @@ bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) switch (event) { case BFA_IOIM_SM_FREE: /* abts and rrq done. Now retry the IO with new tag */ + bfa_ioim_update_iotag(ioim); if (!bfa_ioim_send_ioreq(ioim)) { bfa_sm_set_state(ioim, bfa_ioim_sm_qfull); break; @@ -2526,7 +2527,7 @@ bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m) iotag = be16_to_cpu(rsp->io_tag); ioim = BFA_IOIM_FROM_TAG(fcpim, iotag); - bfa_assert(ioim->iotag == iotag); + bfa_assert(BFA_IOIM_TAG_2_ID(ioim->iotag) == iotag); bfa_trc_fp(ioim->bfa, ioim->iotag); bfa_ioim_cb_profile_comp(fcpim, ioim); @@ -2629,6 +2630,7 @@ bfa_ioim_free(struct bfa_ioim_s *ioim) bfa_stats(ioim->itnim, io_comps); fcpim->ios_active--; + ioim->iotag &= BFA_IOIM_IOTAG_MASK; list_del(&ioim->qe); list_add_tail(&ioim->qe, &fcpim->ioim_free_q); } diff --git a/drivers/scsi/bfa/bfa_fcpim.h b/drivers/scsi/bfa/bfa_fcpim.h index f9334587e02a..1e38dade8423 100644 --- a/drivers/scsi/bfa/bfa_fcpim.h +++ b/drivers/scsi/bfa/bfa_fcpim.h @@ -41,7 +41,7 @@ (__itnim->ioprofile.iocomps[__index]++) #define BFA_IOIM_RETRY_TAG_OFFSET 11 -#define BFA_IOIM_RETRY_TAG_MASK 0x07ff /* 2K IOs */ +#define BFA_IOIM_IOTAG_MASK 0x07ff /* 2K IOs */ #define BFA_IOIM_RETRY_MAX 7 /* Buckets are are 512 bytes to 2MB */ @@ -189,8 +189,9 @@ struct bfa_itnim_s { #define bfa_itnim_is_online(_itnim) ((_itnim)->is_online) #define BFA_FCPIM_MOD(_hal) (&(_hal)->modules.fcpim_mod) +#define BFA_IOIM_TAG_2_ID(_iotag) ((_iotag) & BFA_IOIM_IOTAG_MASK) #define BFA_IOIM_FROM_TAG(_fcpim, _iotag) \ - (&fcpim->ioim_arr[(_iotag & BFA_IOIM_RETRY_TAG_MASK)]) + (&fcpim->ioim_arr[(_iotag & BFA_IOIM_IOTAG_MASK)]) #define BFA_TSKIM_FROM_TAG(_fcpim, _tmtag) \ (&fcpim->tskim_arr[_tmtag & (fcpim->num_tskim_reqs - 1)]) @@ -198,20 +199,21 @@ struct bfa_itnim_s { (_bfa->modules.fcpim_mod.io_profile_start_time) #define bfa_fcpim_get_io_profile(_bfa) \ (_bfa->modules.fcpim_mod.io_profile) +#define bfa_ioim_update_iotag(__ioim) do { \ + uint16_t k = (__ioim)->iotag >> BFA_IOIM_RETRY_TAG_OFFSET; \ + k++; (__ioim)->iotag &= BFA_IOIM_IOTAG_MASK; \ + (__ioim)->iotag |= k << BFA_IOIM_RETRY_TAG_OFFSET; \ +} while (0) static inline bfa_boolean_t -bfa_ioim_get_iotag(struct bfa_ioim_s *ioim) +bfa_ioim_maxretry_reached(struct bfa_ioim_s *ioim) { - u16 k = ioim->iotag; - - k >>= BFA_IOIM_RETRY_TAG_OFFSET; k++; - - if (k > BFA_IOIM_RETRY_MAX) + uint16_t k = ioim->iotag >> BFA_IOIM_RETRY_TAG_OFFSET; + if (k < BFA_IOIM_RETRY_MAX) return BFA_FALSE; - ioim->iotag &= BFA_IOIM_RETRY_TAG_MASK; - ioim->iotag |= k<fcs, fchs->type); if (!bfa_fcs_lport_is_online(lport)) { bfa_stats(lport, uf_recv_drops); @@ -663,8 +664,11 @@ bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport, * Only handles ELS frames for now. */ if (fchs->type != FC_TYPE_ELS) { - bfa_trc(lport->fcs, fchs->type); - bfa_assert(0); + bfa_trc(lport->fcs, fchs->s_id); + bfa_trc(lport->fcs, fchs->d_id); + /* ignore type FC_TYPE_FC_FSS */ + if (fchs->type != FC_TYPE_FC_FSS) + bfa_sm_fault(lport->fcs, fchs->type); return; } diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index 7b0f9725bbc9..53cea3d33351 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c @@ -182,7 +182,7 @@ bfad_im_info(struct Scsi_Host *shost) bfa_get_adapter_model(bfa, model); memset(bfa_buf, 0, sizeof(bfa_buf)); - if (ioc->ctdev) + if (ioc->ctdev && !ioc->fcmode) snprintf(bfa_buf, sizeof(bfa_buf), "Brocade FCOE Adapter, " "model: %s hwpath: %s driver: %s", model, bfad->pci_name, BFAD_DRIVER_VERSION); -- cgit v1.2.3-59-g8ed1b From 395eb20238f5f1d5fba0ae284760a68095dd9e66 Mon Sep 17 00:00:00 2001 From: Krishna Gudipati Date: Mon, 13 Dec 2010 16:23:51 -0800 Subject: [SCSI] bfa: Update the driver version to 2.3.2.3 Signed-off-by: Krishna Gudipati Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfad_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h index 24b6ab18f89d..7f9ea90254cd 100644 --- a/drivers/scsi/bfa/bfad_drv.h +++ b/drivers/scsi/bfa/bfad_drv.h @@ -55,7 +55,7 @@ #ifdef BFA_DRIVER_VERSION #define BFAD_DRIVER_VERSION BFA_DRIVER_VERSION #else -#define BFAD_DRIVER_VERSION "2.3.2.0" +#define BFAD_DRIVER_VERSION "2.3.2.3" #endif #define BFAD_PROTO_NAME FCPI_NAME -- cgit v1.2.3-59-g8ed1b From be858b65cf9701e75bc49ed38c56e5b51ff281cd Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 15 Dec 2010 17:57:20 -0500 Subject: [SCSI] lpfc 8.3.20: Critical fixes - Use for iocbq->context1 to hold the ndlp pointer. - Set ndlp in all iocbs generated from ioctl functions. - Turn parity and serr bits back on after performing sli4 board reset. Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_bsg.c | 40 +++++++++------------------------------- drivers/scsi/lpfc/lpfc_sli.c | 22 ++++++++++++---------- 2 files changed, 21 insertions(+), 41 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 50dbfc8018f6..3330d7951b42 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -162,7 +162,6 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocbq, struct lpfc_iocbq *rspiocbq) { - unsigned long iflags; struct bsg_job_data *dd_data; struct fc_bsg_job *job; IOCB_t *rsp; @@ -173,9 +172,10 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba, int rc = 0; spin_lock_irqsave(&phba->ct_ev_lock, flags); - dd_data = cmdiocbq->context1; + dd_data = cmdiocbq->context2; if (!dd_data) { spin_unlock_irqrestore(&phba->ct_ev_lock, flags); + lpfc_sli_release_iocbq(phba, cmdiocbq); return; } @@ -183,17 +183,9 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba, job = iocb->set_job; job->dd_data = NULL; /* so timeout handler does not reply */ - spin_lock_irqsave(&phba->hbalock, iflags); - cmdiocbq->iocb_flag |= LPFC_IO_WAKE; - if (cmdiocbq->context2 && rspiocbq) - memcpy(&((struct lpfc_iocbq *)cmdiocbq->context2)->iocb, - &rspiocbq->iocb, sizeof(IOCB_t)); - spin_unlock_irqrestore(&phba->hbalock, iflags); - bmp = iocb->bmp; - rspiocbq = iocb->rspiocbq; rsp = &rspiocbq->iocb; - ndlp = iocb->ndlp; + ndlp = cmdiocbq->context1; pci_unmap_sg(phba->pcidev, job->request_payload.sg_list, job->request_payload.sg_cnt, DMA_TO_DEVICE); @@ -220,7 +212,6 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba, rsp->un.genreq64.bdl.bdeSize; lpfc_mbuf_free(phba, bmp->virt, bmp->phys); - lpfc_sli_release_iocbq(phba, rspiocbq); lpfc_sli_release_iocbq(phba, cmdiocbq); lpfc_nlp_put(ndlp); kfree(bmp); @@ -247,9 +238,7 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job) struct ulp_bde64 *bpl = NULL; uint32_t timeout; struct lpfc_iocbq *cmdiocbq = NULL; - struct lpfc_iocbq *rspiocbq = NULL; IOCB_t *cmd; - IOCB_t *rsp; struct lpfc_dmabuf *bmp = NULL; int request_nseg; int reply_nseg; @@ -296,17 +285,10 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job) } cmd = &cmdiocbq->iocb; - rspiocbq = lpfc_sli_get_iocbq(phba); - if (!rspiocbq) { - rc = -ENOMEM; - goto free_cmdiocbq; - } - - rsp = &rspiocbq->iocb; bmp->virt = lpfc_mbuf_alloc(phba, 0, &bmp->phys); if (!bmp->virt) { rc = -ENOMEM; - goto free_rspiocbq; + goto free_cmdiocbq; } INIT_LIST_HEAD(&bmp->list); @@ -358,14 +340,12 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job) cmd->ulpTimeout = timeout; cmdiocbq->iocb_cmpl = lpfc_bsg_send_mgmt_cmd_cmp; - cmdiocbq->context1 = dd_data; - cmdiocbq->context2 = rspiocbq; + cmdiocbq->context1 = ndlp; + cmdiocbq->context2 = dd_data; dd_data->type = TYPE_IOCB; dd_data->context_un.iocb.cmdiocbq = cmdiocbq; - dd_data->context_un.iocb.rspiocbq = rspiocbq; dd_data->context_un.iocb.set_job = job; dd_data->context_un.iocb.bmp = bmp; - dd_data->context_un.iocb.ndlp = ndlp; if (phba->cfg_poll & DISABLE_FCP_RING_INT) { creg_val = readl(phba->HCregaddr); @@ -391,8 +371,6 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job) lpfc_mbuf_free(phba, bmp->virt, bmp->phys); -free_rspiocbq: - lpfc_sli_release_iocbq(phba, rspiocbq); free_cmdiocbq: lpfc_sli_release_iocbq(phba, cmdiocbq); free_bmp: @@ -1220,7 +1198,7 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba, int rc = 0; spin_lock_irqsave(&phba->ct_ev_lock, flags); - dd_data = cmdiocbq->context1; + dd_data = cmdiocbq->context2; /* normal completion and timeout crossed paths, already done */ if (!dd_data) { spin_unlock_irqrestore(&phba->ct_ev_lock, flags); @@ -1369,8 +1347,8 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag, ctiocb->context3 = bmp; ctiocb->iocb_cmpl = lpfc_issue_ct_rsp_cmp; - ctiocb->context1 = dd_data; - ctiocb->context2 = NULL; + ctiocb->context2 = dd_data; + ctiocb->context1 = ndlp; dd_data->type = TYPE_IOCB; dd_data->context_un.iocb.cmdiocbq = ctiocb; dd_data->context_un.iocb.rspiocbq = NULL; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 752601509549..7509de2f4566 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -871,11 +871,9 @@ __lpfc_sli_get_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq) if (piocbq->iocb_flag & LPFC_IO_FCP) { lpfc_cmd = (struct lpfc_scsi_buf *) piocbq->context1; ndlp = lpfc_cmd->rdata->pnode; - } else if (piocbq->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) + } else if ((piocbq->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) && + !(piocbq->iocb_flag & LPFC_IO_LIBDFC)) ndlp = piocbq->context_un.ndlp; - else if (piocbq->iocb.ulpCommand == CMD_XMIT_BLS_RSP64_CX) - ndlp = lpfc_findnode_did(piocbq->vport, - piocbq->iocb.ulpContext); else ndlp = piocbq->context1; @@ -3855,12 +3853,6 @@ lpfc_sli4_brdreset(struct lpfc_hba *phba) phba->pport->fc_myDID = 0; phba->pport->fc_prevDID = 0; - /* Turn off parity checking and serr during the physical reset */ - pci_read_config_word(phba->pcidev, PCI_COMMAND, &cfg_value); - pci_write_config_word(phba->pcidev, PCI_COMMAND, - (cfg_value & - ~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR))); - spin_lock_irq(&phba->hbalock); psli->sli_flag &= ~(LPFC_PROCESS_LA); phba->fcf.fcf_flag = 0; @@ -3880,9 +3872,18 @@ lpfc_sli4_brdreset(struct lpfc_hba *phba) /* Now physically reset the device */ lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "0389 Performing PCI function reset!\n"); + + /* Turn off parity checking and serr during the physical reset */ + pci_read_config_word(phba->pcidev, PCI_COMMAND, &cfg_value); + pci_write_config_word(phba->pcidev, PCI_COMMAND, (cfg_value & + ~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR))); + /* Perform FCoE PCI function reset */ lpfc_pci_function_reset(phba); + /* Restore PCI cmd register */ + pci_write_config_word(phba->pcidev, PCI_COMMAND, cfg_value); + return 0; } @@ -11969,6 +11970,7 @@ lpfc_sli4_seq_abort_acc(struct lpfc_hba *phba, icmd->ulpLe = 1; icmd->ulpClass = CLASS3; icmd->ulpContext = ndlp->nlp_rpi; + ctiocb->context1 = ndlp; ctiocb->iocb_cmpl = NULL; ctiocb->vport = phba->pport; -- cgit v1.2.3-59-g8ed1b From 70f3c073362ef7b5e55c92b83eb2dd9a7fb4e9bf Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 15 Dec 2010 17:57:33 -0500 Subject: [SCSI] lpfc 8.3.20: Implement the FC and SLI async event handlers Implement the FC and SLI async event handlers: - Updated MQ_CREATE_EXT mailbox structure to include fc and SLI async events. - Added the SLI trailer code. - Split physical field into type and number to reflect latest SLI spec. - Changed lpfc_acqe_fcoe to lpfc_acqe_fip to reflect latest Spec changes. - Added lpfc_acqe_fc_la structure for FC link attention async events. - Added lpfc_acqe_sli structure for sli async events. - Added lpfc_sli4_async_fc_evt routine to handle fc la async events. - Added lpfc_sli4_async_sli routine to handle sli async events. - Moved LPFC_TRAILER_CODE_FC to be handled by its own handler function. Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_hw4.h | 129 +++++++++++++++++++++------ drivers/scsi/lpfc/lpfc_init.c | 199 ++++++++++++++++++++++++++++++++++-------- drivers/scsi/lpfc/lpfc_sli.c | 18 ++-- drivers/scsi/lpfc/lpfc_sli.h | 4 +- drivers/scsi/lpfc/lpfc_sli4.h | 4 +- 5 files changed, 283 insertions(+), 71 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 4e3a11b98299..3821ecbf5a8f 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -1134,12 +1134,18 @@ struct lpfc_mbx_mq_create_ext { #define lpfc_mbx_mq_create_ext_async_evt_link_SHIFT LPFC_TRAILER_CODE_LINK #define lpfc_mbx_mq_create_ext_async_evt_link_MASK 0x00000001 #define lpfc_mbx_mq_create_ext_async_evt_link_WORD async_evt_bmap -#define lpfc_mbx_mq_create_ext_async_evt_fcfste_SHIFT LPFC_TRAILER_CODE_FCOE -#define lpfc_mbx_mq_create_ext_async_evt_fcfste_MASK 0x00000001 -#define lpfc_mbx_mq_create_ext_async_evt_fcfste_WORD async_evt_bmap +#define lpfc_mbx_mq_create_ext_async_evt_fip_SHIFT LPFC_TRAILER_CODE_FCOE +#define lpfc_mbx_mq_create_ext_async_evt_fip_MASK 0x00000001 +#define lpfc_mbx_mq_create_ext_async_evt_fip_WORD async_evt_bmap #define lpfc_mbx_mq_create_ext_async_evt_group5_SHIFT LPFC_TRAILER_CODE_GRP5 #define lpfc_mbx_mq_create_ext_async_evt_group5_MASK 0x00000001 #define lpfc_mbx_mq_create_ext_async_evt_group5_WORD async_evt_bmap +#define lpfc_mbx_mq_create_ext_async_evt_fc_SHIFT LPFC_TRAILER_CODE_FC +#define lpfc_mbx_mq_create_ext_async_evt_fc_MASK 0x00000001 +#define lpfc_mbx_mq_create_ext_async_evt_fc_WORD async_evt_bmap +#define lpfc_mbx_mq_create_ext_async_evt_sli_SHIFT LPFC_TRAILER_CODE_SLI +#define lpfc_mbx_mq_create_ext_async_evt_sli_MASK 0x00000001 +#define lpfc_mbx_mq_create_ext_async_evt_sli_WORD async_evt_bmap struct mq_context context; struct dma_address page[LPFC_MAX_MQ_PAGE]; } request; @@ -1393,7 +1399,7 @@ struct lpfc_mbx_query_fw_cfg { #define lpfc_function_mode_dal_WORD function_mode #define lpfc_function_mode_lro_SHIFT 9 #define lpfc_function_mode_lro_MASK 0x00000001 -#define lpfc_function_mode_lro_WORD function_mode9 +#define lpfc_function_mode_lro_WORD function_mode #define lpfc_function_mode_flex10_SHIFT 10 #define lpfc_function_mode_flex10_MASK 0x00000001 #define lpfc_function_mode_flex10_WORD function_mode @@ -2162,6 +2168,7 @@ struct lpfc_mcqe { #define LPFC_TRAILER_CODE_DCBX 0x3 #define LPFC_TRAILER_CODE_GRP5 0x5 #define LPFC_TRAILER_CODE_FC 0x10 +#define LPFC_TRAILER_CODE_SLI 0x11 }; struct lpfc_acqe_link { @@ -2187,11 +2194,12 @@ struct lpfc_acqe_link { #define LPFC_ASYNC_LINK_STATUS_UP 0x1 #define LPFC_ASYNC_LINK_STATUS_LOGICAL_DOWN 0x2 #define LPFC_ASYNC_LINK_STATUS_LOGICAL_UP 0x3 -#define lpfc_acqe_link_physical_SHIFT 0 -#define lpfc_acqe_link_physical_MASK 0x000000FF -#define lpfc_acqe_link_physical_WORD word0 -#define LPFC_ASYNC_LINK_PORT_A 0x0 -#define LPFC_ASYNC_LINK_PORT_B 0x1 +#define lpfc_acqe_link_type_SHIFT 6 +#define lpfc_acqe_link_type_MASK 0x00000003 +#define lpfc_acqe_link_type_WORD word0 +#define lpfc_acqe_link_number_SHIFT 0 +#define lpfc_acqe_link_number_MASK 0x0000003F +#define lpfc_acqe_link_number_WORD word0 uint32_t word1; #define lpfc_acqe_link_fault_SHIFT 0 #define lpfc_acqe_link_fault_MASK 0x000000FF @@ -2199,29 +2207,31 @@ struct lpfc_acqe_link { #define LPFC_ASYNC_LINK_FAULT_NONE 0x0 #define LPFC_ASYNC_LINK_FAULT_LOCAL 0x1 #define LPFC_ASYNC_LINK_FAULT_REMOTE 0x2 -#define lpfc_acqe_qos_link_speed_SHIFT 16 -#define lpfc_acqe_qos_link_speed_MASK 0x0000FFFF -#define lpfc_acqe_qos_link_speed_WORD word1 +#define lpfc_acqe_logical_link_speed_SHIFT 16 +#define lpfc_acqe_logical_link_speed_MASK 0x0000FFFF +#define lpfc_acqe_logical_link_speed_WORD word1 uint32_t event_tag; uint32_t trailer; +#define LPFC_LINK_EVENT_TYPE_PHYSICAL 0x0 +#define LPFC_LINK_EVENT_TYPE_VIRTUAL 0x1 }; -struct lpfc_acqe_fcoe { +struct lpfc_acqe_fip { uint32_t index; uint32_t word1; -#define lpfc_acqe_fcoe_fcf_count_SHIFT 0 -#define lpfc_acqe_fcoe_fcf_count_MASK 0x0000FFFF -#define lpfc_acqe_fcoe_fcf_count_WORD word1 -#define lpfc_acqe_fcoe_event_type_SHIFT 16 -#define lpfc_acqe_fcoe_event_type_MASK 0x0000FFFF -#define lpfc_acqe_fcoe_event_type_WORD word1 -#define LPFC_FCOE_EVENT_TYPE_NEW_FCF 0x1 -#define LPFC_FCOE_EVENT_TYPE_FCF_TABLE_FULL 0x2 -#define LPFC_FCOE_EVENT_TYPE_FCF_DEAD 0x3 -#define LPFC_FCOE_EVENT_TYPE_CVL 0x4 -#define LPFC_FCOE_EVENT_TYPE_FCF_PARAM_MOD 0x5 +#define lpfc_acqe_fip_fcf_count_SHIFT 0 +#define lpfc_acqe_fip_fcf_count_MASK 0x0000FFFF +#define lpfc_acqe_fip_fcf_count_WORD word1 +#define lpfc_acqe_fip_event_type_SHIFT 16 +#define lpfc_acqe_fip_event_type_MASK 0x0000FFFF +#define lpfc_acqe_fip_event_type_WORD word1 uint32_t event_tag; uint32_t trailer; +#define LPFC_FIP_EVENT_TYPE_NEW_FCF 0x1 +#define LPFC_FIP_EVENT_TYPE_FCF_TABLE_FULL 0x2 +#define LPFC_FIP_EVENT_TYPE_FCF_DEAD 0x3 +#define LPFC_FIP_EVENT_TYPE_CVL 0x4 +#define LPFC_FIP_EVENT_TYPE_FCF_PARAM_MOD 0x5 }; struct lpfc_acqe_dcbx { @@ -2233,9 +2243,12 @@ struct lpfc_acqe_dcbx { struct lpfc_acqe_grp5 { uint32_t word0; -#define lpfc_acqe_grp5_pport_SHIFT 0 -#define lpfc_acqe_grp5_pport_MASK 0x000000FF -#define lpfc_acqe_grp5_pport_WORD word0 +#define lpfc_acqe_grp5_type_SHIFT 6 +#define lpfc_acqe_grp5_type_MASK 0x00000003 +#define lpfc_acqe_grp5_type_WORD word0 +#define lpfc_acqe_grp5_number_SHIFT 0 +#define lpfc_acqe_grp5_number_MASK 0x0000003F +#define lpfc_acqe_grp5_number_WORD word0 uint32_t word1; #define lpfc_acqe_grp5_llink_spd_SHIFT 16 #define lpfc_acqe_grp5_llink_spd_MASK 0x0000FFFF @@ -2244,6 +2257,68 @@ struct lpfc_acqe_grp5 { uint32_t trailer; }; +struct lpfc_acqe_fc_la { + uint32_t word0; +#define lpfc_acqe_fc_la_speed_SHIFT 24 +#define lpfc_acqe_fc_la_speed_MASK 0x000000FF +#define lpfc_acqe_fc_la_speed_WORD word0 +#define LPFC_FC_LA_SPEED_UNKOWN 0x0 +#define LPFC_FC_LA_SPEED_1G 0x1 +#define LPFC_FC_LA_SPEED_2G 0x2 +#define LPFC_FC_LA_SPEED_4G 0x4 +#define LPFC_FC_LA_SPEED_8G 0x8 +#define LPFC_FC_LA_SPEED_10G 0xA +#define LPFC_FC_LA_SPEED_16G 0x10 +#define lpfc_acqe_fc_la_topology_SHIFT 16 +#define lpfc_acqe_fc_la_topology_MASK 0x000000FF +#define lpfc_acqe_fc_la_topology_WORD word0 +#define LPFC_FC_LA_TOP_UNKOWN 0x0 +#define LPFC_FC_LA_TOP_P2P 0x1 +#define LPFC_FC_LA_TOP_FCAL 0x2 +#define LPFC_FC_LA_TOP_INTERNAL_LOOP 0x3 +#define LPFC_FC_LA_TOP_SERDES_LOOP 0x4 +#define lpfc_acqe_fc_la_att_type_SHIFT 8 +#define lpfc_acqe_fc_la_att_type_MASK 0x000000FF +#define lpfc_acqe_fc_la_att_type_WORD word0 +#define LPFC_FC_LA_TYPE_LINK_UP 0x1 +#define LPFC_FC_LA_TYPE_LINK_DOWN 0x2 +#define LPFC_FC_LA_TYPE_NO_HARD_ALPA 0x3 +#define lpfc_acqe_fc_la_port_type_SHIFT 6 +#define lpfc_acqe_fc_la_port_type_MASK 0x00000003 +#define lpfc_acqe_fc_la_port_type_WORD word0 +#define LPFC_LINK_TYPE_ETHERNET 0x0 +#define LPFC_LINK_TYPE_FC 0x1 +#define lpfc_acqe_fc_la_port_number_SHIFT 0 +#define lpfc_acqe_fc_la_port_number_MASK 0x0000003F +#define lpfc_acqe_fc_la_port_number_WORD word0 + uint32_t word1; +#define lpfc_acqe_fc_la_llink_spd_SHIFT 16 +#define lpfc_acqe_fc_la_llink_spd_MASK 0x0000FFFF +#define lpfc_acqe_fc_la_llink_spd_WORD word1 +#define lpfc_acqe_fc_la_fault_SHIFT 0 +#define lpfc_acqe_fc_la_fault_MASK 0x000000FF +#define lpfc_acqe_fc_la_fault_WORD word1 +#define LPFC_FC_LA_FAULT_NONE 0x0 +#define LPFC_FC_LA_FAULT_LOCAL 0x1 +#define LPFC_FC_LA_FAULT_REMOTE 0x2 + uint32_t event_tag; + uint32_t trailer; +#define LPFC_FC_LA_EVENT_TYPE_FC_LINK 0x1 +#define LPFC_FC_LA_EVENT_TYPE_SHARED_LINK 0x2 +}; + +struct lpfc_acqe_sli { + uint32_t event_data1; + uint32_t event_data2; + uint32_t reserved; + uint32_t trailer; +#define LPFC_SLI_EVENT_TYPE_PORT_ERROR 0x1 +#define LPFC_SLI_EVENT_TYPE_OVER_TEMP 0x2 +#define LPFC_SLI_EVENT_TYPE_NORM_TEMP 0x3 +#define LPFC_SLI_EVENT_TYPE_NVLOG_POST 0x4 +#define LPFC_SLI_EVENT_TYPE_DIAG_DUMP 0x5 +}; + /* * Define the bootstrap mailbox (bmbx) region used to communicate * mailbox command between the host and port. The mailbox consists diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 70ba1895b0a1..311671d3216f 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -3149,11 +3149,11 @@ lpfc_sli4_parse_latt_link_speed(struct lpfc_hba *phba, } /** - * lpfc_sli4_async_link_evt - Process the asynchronous FC or FCoE link event + * lpfc_sli4_async_link_evt - Process the asynchronous FCoE link event * @phba: pointer to lpfc hba data structure. * @acqe_link: pointer to the async link completion queue entry. * - * This routine is to handle the SLI4 asynchronous link event. + * This routine is to handle the SLI4 asynchronous FCoE link event. **/ static void lpfc_sli4_async_link_evt(struct lpfc_hba *phba, @@ -3210,12 +3210,25 @@ lpfc_sli4_async_link_evt(struct lpfc_hba *phba, bf_get(lpfc_acqe_link_duplex, acqe_link); phba->sli4_hba.link_state.status = bf_get(lpfc_acqe_link_status, acqe_link); - phba->sli4_hba.link_state.physical = - bf_get(lpfc_acqe_link_physical, acqe_link); + phba->sli4_hba.link_state.type = + bf_get(lpfc_acqe_link_type, acqe_link); + phba->sli4_hba.link_state.number = + bf_get(lpfc_acqe_link_number, acqe_link); phba->sli4_hba.link_state.fault = bf_get(lpfc_acqe_link_fault, acqe_link); phba->sli4_hba.link_state.logical_speed = - bf_get(lpfc_acqe_qos_link_speed, acqe_link); + bf_get(lpfc_acqe_logical_link_speed, acqe_link); + lpfc_printf_log(phba, KERN_INFO, LOG_SLI, + "2900 Async FCoE Link event - Speed:%dGBit duplex:x%x " + "LA Type:x%x Port Type:%d Port Number:%d Logical " + "speed:%dMbps Fault:%d\n", + phba->sli4_hba.link_state.speed, + phba->sli4_hba.link_state.topology, + phba->sli4_hba.link_state.status, + phba->sli4_hba.link_state.type, + phba->sli4_hba.link_state.number, + phba->sli4_hba.link_state.logical_speed * 10, + phba->sli4_hba.link_state.fault); /* * For FC Mode: issue the READ_TOPOLOGY mailbox command to fetch * topology info. Note: Optional for non FC-AL ports. @@ -3261,6 +3274,118 @@ out_free_pmb: mempool_free(pmb, phba->mbox_mem_pool); } +/** + * lpfc_sli4_async_fc_evt - Process the asynchronous FC link event + * @phba: pointer to lpfc hba data structure. + * @acqe_fc: pointer to the async fc completion queue entry. + * + * This routine is to handle the SLI4 asynchronous FC event. It will simply log + * that the event was received and then issue a read_topology mailbox command so + * that the rest of the driver will treat it the same as SLI3. + **/ +static void +lpfc_sli4_async_fc_evt(struct lpfc_hba *phba, struct lpfc_acqe_fc_la *acqe_fc) +{ + struct lpfc_dmabuf *mp; + LPFC_MBOXQ_t *pmb; + int rc; + + if (bf_get(lpfc_trailer_type, acqe_fc) != + LPFC_FC_LA_EVENT_TYPE_FC_LINK) { + lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + "2895 Non FC link Event detected.(%d)\n", + bf_get(lpfc_trailer_type, acqe_fc)); + return; + } + /* Keep the link status for extra SLI4 state machine reference */ + phba->sli4_hba.link_state.speed = + bf_get(lpfc_acqe_fc_la_speed, acqe_fc); + phba->sli4_hba.link_state.duplex = LPFC_ASYNC_LINK_DUPLEX_FULL; + phba->sli4_hba.link_state.topology = + bf_get(lpfc_acqe_fc_la_topology, acqe_fc); + phba->sli4_hba.link_state.status = + bf_get(lpfc_acqe_fc_la_att_type, acqe_fc); + phba->sli4_hba.link_state.type = + bf_get(lpfc_acqe_fc_la_port_type, acqe_fc); + phba->sli4_hba.link_state.number = + bf_get(lpfc_acqe_fc_la_port_number, acqe_fc); + phba->sli4_hba.link_state.fault = + bf_get(lpfc_acqe_link_fault, acqe_fc); + phba->sli4_hba.link_state.logical_speed = + bf_get(lpfc_acqe_fc_la_llink_spd, acqe_fc); + lpfc_printf_log(phba, KERN_INFO, LOG_SLI, + "2896 Async FC event - Speed:%dGBaud Topology:x%x " + "LA Type:x%x Port Type:%d Port Number:%d Logical speed:" + "%dMbps Fault:%d\n", + phba->sli4_hba.link_state.speed, + phba->sli4_hba.link_state.topology, + phba->sli4_hba.link_state.status, + phba->sli4_hba.link_state.type, + phba->sli4_hba.link_state.number, + phba->sli4_hba.link_state.logical_speed * 10, + phba->sli4_hba.link_state.fault); + pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); + if (!pmb) { + lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + "2897 The mboxq allocation failed\n"); + return; + } + mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); + if (!mp) { + lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + "2898 The lpfc_dmabuf allocation failed\n"); + goto out_free_pmb; + } + mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys); + if (!mp->virt) { + lpfc_printf_log(phba, KERN_ERR, LOG_SLI, + "2899 The mbuf allocation failed\n"); + goto out_free_dmabuf; + } + + /* Cleanup any outstanding ELS commands */ + lpfc_els_flush_all_cmd(phba); + + /* Block ELS IOCBs until we have done process link event */ + phba->sli.ring[LPFC_ELS_RING].flag |= LPFC_STOP_IOCB_EVENT; + + /* Update link event statistics */ + phba->sli.slistat.link_event++; + + /* Create lpfc_handle_latt mailbox command from link ACQE */ + lpfc_read_topology(phba, pmb, mp); + pmb->mbox_cmpl = lpfc_mbx_cmpl_read_topology; + pmb->vport = phba->pport; + + rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); + if (rc == MBX_NOT_FINISHED) + goto out_free_dmabuf; + return; + +out_free_dmabuf: + kfree(mp); +out_free_pmb: + mempool_free(pmb, phba->mbox_mem_pool); +} + +/** + * lpfc_sli4_async_sli_evt - Process the asynchronous SLI link event + * @phba: pointer to lpfc hba data structure. + * @acqe_fc: pointer to the async SLI completion queue entry. + * + * This routine is to handle the SLI4 asynchronous SLI events. + **/ +static void +lpfc_sli4_async_sli_evt(struct lpfc_hba *phba, struct lpfc_acqe_sli *acqe_sli) +{ + lpfc_printf_log(phba, KERN_INFO, LOG_SLI, + "2901 Async SLI event - Event Data1:x%08x Event Data2:" + "x%08x SLI Event Type:%d", + acqe_sli->event_data1, acqe_sli->event_data2, + bf_get(lpfc_trailer_type, acqe_sli)); + return; +} + /** * lpfc_sli4_perform_vport_cvl - Perform clear virtual link on a vport * @vport: pointer to vport data structure. @@ -3348,9 +3473,9 @@ lpfc_sli4_perform_all_vport_cvl(struct lpfc_hba *phba) **/ static void lpfc_sli4_async_fip_evt(struct lpfc_hba *phba, - struct lpfc_acqe_fcoe *acqe_fcoe) + struct lpfc_acqe_fip *acqe_fip) { - uint8_t event_type = bf_get(lpfc_acqe_fcoe_event_type, acqe_fcoe); + uint8_t event_type = bf_get(lpfc_trailer_type, acqe_fip); int rc; struct lpfc_vport *vport; struct lpfc_nodelist *ndlp; @@ -3359,25 +3484,25 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba, struct lpfc_vport **vports; int i; - phba->fc_eventTag = acqe_fcoe->event_tag; - phba->fcoe_eventtag = acqe_fcoe->event_tag; + phba->fc_eventTag = acqe_fip->event_tag; + phba->fcoe_eventtag = acqe_fip->event_tag; switch (event_type) { - case LPFC_FCOE_EVENT_TYPE_NEW_FCF: - case LPFC_FCOE_EVENT_TYPE_FCF_PARAM_MOD: - if (event_type == LPFC_FCOE_EVENT_TYPE_NEW_FCF) + case LPFC_FIP_EVENT_TYPE_NEW_FCF: + case LPFC_FIP_EVENT_TYPE_FCF_PARAM_MOD: + if (event_type == LPFC_FIP_EVENT_TYPE_NEW_FCF) lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY, "2546 New FCF event, evt_tag:x%x, " "index:x%x\n", - acqe_fcoe->event_tag, - acqe_fcoe->index); + acqe_fip->event_tag, + acqe_fip->index); else lpfc_printf_log(phba, KERN_WARNING, LOG_FIP | LOG_DISCOVERY, "2788 FCF param modified event, " "evt_tag:x%x, index:x%x\n", - acqe_fcoe->event_tag, - acqe_fcoe->index); + acqe_fip->event_tag, + acqe_fip->index); if (phba->fcf.fcf_flag & FCF_DISCOVERY) { /* * During period of FCF discovery, read the FCF @@ -3388,8 +3513,8 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba, LOG_DISCOVERY, "2779 Read FCF (x%x) for updating " "roundrobin FCF failover bmask\n", - acqe_fcoe->index); - rc = lpfc_sli4_read_fcf_rec(phba, acqe_fcoe->index); + acqe_fip->index); + rc = lpfc_sli4_read_fcf_rec(phba, acqe_fip->index); } /* If the FCF discovery is in progress, do nothing. */ @@ -3415,7 +3540,7 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba, lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, "2770 Start FCF table scan per async FCF " "event, evt_tag:x%x, index:x%x\n", - acqe_fcoe->event_tag, acqe_fcoe->index); + acqe_fip->event_tag, acqe_fip->index); rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba, LPFC_FCOE_FCF_GET_FIRST); if (rc) @@ -3424,17 +3549,17 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba, "command failed (x%x)\n", rc); break; - case LPFC_FCOE_EVENT_TYPE_FCF_TABLE_FULL: + case LPFC_FIP_EVENT_TYPE_FCF_TABLE_FULL: lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "2548 FCF Table full count 0x%x tag 0x%x\n", - bf_get(lpfc_acqe_fcoe_fcf_count, acqe_fcoe), - acqe_fcoe->event_tag); + bf_get(lpfc_acqe_fip_fcf_count, acqe_fip), + acqe_fip->event_tag); break; - case LPFC_FCOE_EVENT_TYPE_FCF_DEAD: + case LPFC_FIP_EVENT_TYPE_FCF_DEAD: lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY, "2549 FCF (x%x) disconnected from network, " - "tag:x%x\n", acqe_fcoe->index, acqe_fcoe->event_tag); + "tag:x%x\n", acqe_fip->index, acqe_fip->event_tag); /* * If we are in the middle of FCF failover process, clear * the corresponding FCF bit in the roundrobin bitmap. @@ -3443,13 +3568,13 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba, if (phba->fcf.fcf_flag & FCF_DISCOVERY) { spin_unlock_irq(&phba->hbalock); /* Update FLOGI FCF failover eligible FCF bmask */ - lpfc_sli4_fcf_rr_index_clear(phba, acqe_fcoe->index); + lpfc_sli4_fcf_rr_index_clear(phba, acqe_fip->index); break; } spin_unlock_irq(&phba->hbalock); /* If the event is not for currently used fcf do nothing */ - if (phba->fcf.current_rec.fcf_indx != acqe_fcoe->index) + if (phba->fcf.current_rec.fcf_indx != acqe_fip->index) break; /* @@ -3466,7 +3591,7 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba, lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, "2771 Start FCF fast failover process due to " "FCF DEAD event: evt_tag:x%x, fcf_index:x%x " - "\n", acqe_fcoe->event_tag, acqe_fcoe->index); + "\n", acqe_fip->event_tag, acqe_fip->index); rc = lpfc_sli4_redisc_fcf_table(phba); if (rc) { lpfc_printf_log(phba, KERN_ERR, LOG_FIP | @@ -3493,12 +3618,12 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba, lpfc_sli4_perform_all_vport_cvl(phba); } break; - case LPFC_FCOE_EVENT_TYPE_CVL: + case LPFC_FIP_EVENT_TYPE_CVL: lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY, "2718 Clear Virtual Link Received for VPI 0x%x" - " tag 0x%x\n", acqe_fcoe->index, acqe_fcoe->event_tag); + " tag 0x%x\n", acqe_fip->index, acqe_fip->event_tag); vport = lpfc_find_vport_by_vpid(phba, - acqe_fcoe->index - phba->vpi_base); + acqe_fip->index - phba->vpi_base); ndlp = lpfc_sli4_perform_vport_cvl(vport); if (!ndlp) break; @@ -3549,7 +3674,7 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba, lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, "2773 Start FCF failover per CVL, " - "evt_tag:x%x\n", acqe_fcoe->event_tag); + "evt_tag:x%x\n", acqe_fip->event_tag); rc = lpfc_sli4_redisc_fcf_table(phba); if (rc) { lpfc_printf_log(phba, KERN_ERR, LOG_FIP | @@ -3577,7 +3702,7 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba, default: lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "0288 Unknown FCoE event type 0x%x event tag " - "0x%x\n", event_type, acqe_fcoe->event_tag); + "0x%x\n", event_type, acqe_fip->event_tag); break; } } @@ -3650,13 +3775,11 @@ void lpfc_sli4_async_event_proc(struct lpfc_hba *phba) /* Process the asynchronous event */ switch (bf_get(lpfc_trailer_code, &cq_event->cqe.mcqe_cmpl)) { case LPFC_TRAILER_CODE_LINK: - case LPFC_TRAILER_CODE_FC: lpfc_sli4_async_link_evt(phba, &cq_event->cqe.acqe_link); break; case LPFC_TRAILER_CODE_FCOE: - lpfc_sli4_async_fip_evt(phba, - &cq_event->cqe.acqe_fcoe); + lpfc_sli4_async_fip_evt(phba, &cq_event->cqe.acqe_fip); break; case LPFC_TRAILER_CODE_DCBX: lpfc_sli4_async_dcbx_evt(phba, @@ -3666,6 +3789,12 @@ void lpfc_sli4_async_event_proc(struct lpfc_hba *phba) lpfc_sli4_async_grp5_evt(phba, &cq_event->cqe.acqe_grp5); break; + case LPFC_TRAILER_CODE_FC: + lpfc_sli4_async_fc_evt(phba, &cq_event->cqe.acqe_fc); + break; + case LPFC_TRAILER_CODE_SLI: + lpfc_sli4_async_sli_evt(phba, &cq_event->cqe.acqe_sli); + break; default: lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "1804 Invalid asynchrous event code: " diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 7509de2f4566..8df959ea9669 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -10561,16 +10561,20 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq, length, LPFC_SLI4_MBX_EMBED); mq_create_ext = &mbox->u.mqe.un.mq_create_ext; - bf_set(lpfc_mbx_mq_create_ext_num_pages, &mq_create_ext->u.request, - mq->page_count); - bf_set(lpfc_mbx_mq_create_ext_async_evt_link, &mq_create_ext->u.request, - 1); - bf_set(lpfc_mbx_mq_create_ext_async_evt_fcfste, + bf_set(lpfc_mbx_mq_create_ext_num_pages, + &mq_create_ext->u.request, mq->page_count); + bf_set(lpfc_mbx_mq_create_ext_async_evt_link, + &mq_create_ext->u.request, 1); + bf_set(lpfc_mbx_mq_create_ext_async_evt_fip, &mq_create_ext->u.request, 1); bf_set(lpfc_mbx_mq_create_ext_async_evt_group5, &mq_create_ext->u.request, 1); - bf_set(lpfc_mq_context_cq_id, &mq_create_ext->u.request.context, - cq->queue_id); + bf_set(lpfc_mbx_mq_create_ext_async_evt_fc, + &mq_create_ext->u.request, 1); + bf_set(lpfc_mbx_mq_create_ext_async_evt_sli, + &mq_create_ext->u.request, 1); + bf_set(lpfc_mq_context_cq_id, + &mq_create_ext->u.request.context, cq->queue_id); bf_set(lpfc_mq_context_valid, &mq_create_ext->u.request.context, 1); switch (mq->entry_count) { default: diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index 402a0737076c..453577c21c14 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h @@ -34,9 +34,11 @@ struct lpfc_cq_event { union { struct lpfc_mcqe mcqe_cmpl; struct lpfc_acqe_link acqe_link; - struct lpfc_acqe_fcoe acqe_fcoe; + struct lpfc_acqe_fip acqe_fip; struct lpfc_acqe_dcbx acqe_dcbx; struct lpfc_acqe_grp5 acqe_grp5; + struct lpfc_acqe_fc_la acqe_fc; + struct lpfc_acqe_sli acqe_sli; struct lpfc_rcqe rcqe_cmpl; struct sli4_wcqe_xri_aborted wcqe_axri; struct lpfc_wcqe_complete wcqe_cmpl; diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 8ced5983d3e3..f96eae51d07c 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -137,9 +137,11 @@ struct lpfc_sli4_link { uint8_t speed; uint8_t duplex; uint8_t status; - uint8_t physical; + uint8_t type; + uint8_t number; uint8_t fault; uint16_t logical_speed; + uint16_t topology; }; struct lpfc_fcf_rec { -- cgit v1.2.3-59-g8ed1b From 2fcee4bf874a8ae72ada68b62728d1fdeb30e3d4 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 15 Dec 2010 17:57:46 -0500 Subject: [SCSI] lpfc 8.3.20: Implement new SLI4 init procedures based on if_type Implement new SLI4 init procedures based on if_type: - Add structure changes for new SLIPORT registers and BAR changes. - Update register names to be consistent with inteface spec terms. - Added union to encapsulate Hardward error registers. - Rework lpfc_sli4_post_status_check() around SLI-4's SLI_INTF type - Removed the lpfc_sli4_fw_cfg_check routine - Segmented driver logic to include evaluation of the if_type to engage different behaviors. Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_hw4.h | 108 +++---- drivers/scsi/lpfc/lpfc_init.c | 660 ++++++++++++++++++++++++++++-------------- drivers/scsi/lpfc/lpfc_sli.c | 77 +++-- drivers/scsi/lpfc/lpfc_sli4.h | 50 ++-- 4 files changed, 569 insertions(+), 326 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 3821ecbf5a8f..94c1aa1136de 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -460,42 +460,41 @@ struct lpfc_register { uint32_t word0; }; -/* The SLI4 INTF register offset is common to all if_type values. */ -#define LPFC_SLI_INTF 0x0058 - /* The following BAR0 Registers apply to SLI4 if_type 0 UCNAs. */ #define LPFC_UERR_STATUS_HI 0x00A4 #define LPFC_UERR_STATUS_LO 0x00A0 #define LPFC_UE_MASK_HI 0x00AC #define LPFC_UE_MASK_LO 0x00A8 -#define LPFC_HST_STATE 0x00AC -#define lpfc_hst_state_perr_SHIFT 31 -#define lpfc_hst_state_perr_MASK 0x1 -#define lpfc_hst_state_perr_WORD word0 -#define lpfc_hst_state_sfi_SHIFT 30 -#define lpfc_hst_state_sfi_MASK 0x1 -#define lpfc_hst_state_sfi_WORD word0 -#define lpfc_hst_state_nip_SHIFT 29 -#define lpfc_hst_state_nip_MASK 0x1 -#define lpfc_hst_state_nip_WORD word0 -#define lpfc_hst_state_ipc_SHIFT 28 -#define lpfc_hst_state_ipc_MASK 0x1 -#define lpfc_hst_state_ipc_WORD word0 -#define lpfc_hst_state_xrom_SHIFT 27 -#define lpfc_hst_state_xrom_MASK 0x1 -#define lpfc_hst_state_xrom_WORD word0 -#define lpfc_hst_state_dl_SHIFT 26 -#define lpfc_hst_state_dl_MASK 0x1 -#define lpfc_hst_state_dl_WORD word0 -#define lpfc_hst_state_port_status_SHIFT 0 -#define lpfc_hst_state_port_status_MASK 0xFFFF -#define lpfc_hst_state_port_status_WORD word0 +/* The following BAR0 register sets are defined for if_type 0 and 2 UCNAs. */ +#define LPFC_SLI_INTF 0x0058 + +#define LPFC_SLIPORT_IF2_SMPHR 0x0400 +#define lpfc_port_smphr_perr_SHIFT 31 +#define lpfc_port_smphr_perr_MASK 0x1 +#define lpfc_port_smphr_perr_WORD word0 +#define lpfc_port_smphr_sfi_SHIFT 30 +#define lpfc_port_smphr_sfi_MASK 0x1 +#define lpfc_port_smphr_sfi_WORD word0 +#define lpfc_port_smphr_nip_SHIFT 29 +#define lpfc_port_smphr_nip_MASK 0x1 +#define lpfc_port_smphr_nip_WORD word0 +#define lpfc_port_smphr_ipc_SHIFT 28 +#define lpfc_port_smphr_ipc_MASK 0x1 +#define lpfc_port_smphr_ipc_WORD word0 +#define lpfc_port_smphr_scr1_SHIFT 27 +#define lpfc_port_smphr_scr1_MASK 0x1 +#define lpfc_port_smphr_scr1_WORD word0 +#define lpfc_port_smphr_scr2_SHIFT 26 +#define lpfc_port_smphr_scr2_MASK 0x1 +#define lpfc_port_smphr_scr2_WORD word0 +#define lpfc_port_smphr_host_scratch_SHIFT 16 +#define lpfc_port_smphr_host_scratch_MASK 0xFF +#define lpfc_port_smphr_host_scratch_WORD word0 +#define lpfc_port_smphr_port_status_SHIFT 0 +#define lpfc_port_smphr_port_status_MASK 0xFFFF +#define lpfc_port_smphr_port_status_WORD word0 -/* - * The following Port Status Values apply to SLI4, if_type 0 and 2 - * UCNAs. - */ #define LPFC_POST_STAGE_POWER_ON_RESET 0x0000 #define LPFC_POST_STAGE_AWAITING_HOST_RDY 0x0001 #define LPFC_POST_STAGE_HOST_RDY 0x0002 @@ -527,36 +526,8 @@ struct lpfc_register { #define LPFC_POST_STAGE_RC_DONE 0x0B07 #define LPFC_POST_STAGE_REBOOT_SYSTEM 0x0B08 #define LPFC_POST_STAGE_MAC_ADDRESS 0x0C00 -#define LPFC_POST_STAGE_ARMFW_READY 0xC000 -#define LPFC_POST_STAGE_ARMFW_UE 0xF000 - - -/* The following BAR0 register sets are defined for if_type 2 UCNAs. */ -#define LPFC_SLIPORT_SEMAPHORE 0x0400 -#define lpfc_sliport_smphr_perr_SHIFT 31 -#define lpfc_sliport_smphr_perr_MASK 0x1 -#define lpfc_sliport_smphr_perr_WORD word0 -#define lpfc_sliport_smphr_sfi_SHIFT 30 -#define lpfc_sliport_smphr_sfi_MASK 0x1 -#define lpfc_sliport_smphr_sfi_WORD word0 -#define lpfc_sliport_smphr_nip_SHIFT 29 -#define lpfc_sliport_smphr_nip_MASK 0x1 -#define lpfc_sliport_smphr_nip_WORD word0 -#define lpfc_sliport_smphr_ipc_SHIFT 28 -#define lpfc_sliport_smphr_ipc_MASK 0x1 -#define lpfc_sliport_smphr_ipc_WORD word0 -#define lpfc_sliport_smphr_scr1_SHIFT 27 -#define lpfc_sliport_smphr_scr1_MASK 0x1 -#define lpfc_sliport_smphr_scr1_WORD word0 -#define lpfc_sliport_smphr_scr2_SHIFT 26 -#define lpfc_sliport_smphr_scr2_MASK 0x1 -#define lpfc_sliport_smphr_scr2_WORD word0 -#define lpfc_sliport_smphr_host_scratch_SHIFT 16 -#define lpfc_sliport_smphr_host_scratch_MASK 0xFF -#define lpfc_sliport_smphr_host_scratch_WORD word0 -#define lpfc_sliport_smphr_port_status_SHIFT 0 -#define lpfc_sliport_smphr_port_status_MASK 0xFFFF -#define lpfc_sliport_smphr_port_status_WORD word0 +#define LPFC_POST_STAGE_PORT_READY 0xC000 +#define LPFC_POST_STAGE_PORT_UE 0xF000 #define LPFC_SLIPORT_STATUS 0x0404 #define lpfc_sliport_status_err_SHIFT 31 @@ -574,8 +545,9 @@ struct lpfc_register { #define lpfc_sliport_status_rdy_SHIFT 23 #define lpfc_sliport_status_rdy_MASK 0x1 #define lpfc_sliport_status_rdy_WORD word0 +#define MAX_IF_TYPE_2_RESETS 1000 -#define LPFC_SLIPORT_CONTROL 0x0408 +#define LPFC_SLIPORT_CNTRL 0x0408 #define lpfc_sliport_ctrl_end_SHIFT 30 #define lpfc_sliport_ctrl_end_MASK 0x1 #define lpfc_sliport_ctrl_end_WORD word0 @@ -584,11 +556,16 @@ struct lpfc_register { #define lpfc_sliport_ctrl_ip_SHIFT 27 #define lpfc_sliport_ctrl_ip_MASK 0x1 #define lpfc_sliport_ctrl_ip_WORD word0 +#define LPFC_SLIPORT_INIT_PORT 1 -#define LPFC_SLIPORT_ERROR_1 0x040C -#define LPFC_SLIPORT_ERROR_2 0x0410 +#define LPFC_SLIPORT_ERR_1 0x040C +#define LPFC_SLIPORT_ERR_2 0x0410 + +/* The following Registers apply to SLI4 if_type 0 UCNAs. They typically + * reside in BAR 2. + */ +#define LPFC_SLIPORT_IF0_SMPHR 0x00AC -/* BAR1 Registers */ #define LPFC_IMR_MASK_ALL 0xFFFFFFFF #define LPFC_ISCR_CLEAR_ALL 0xFFFFFFFF @@ -647,7 +624,7 @@ struct lpfc_register { * The Doorbell registers defined here exist in different BAR * register sets depending on the UCNA Port's reported if_type * value. For UCNA ports running SLI4 and if_type 0, they reside in - * BAR2. For UCNA ports running SLI4 and if_type 2, they reside in + * BAR4. For UCNA ports running SLI4 and if_type 2, they reside in * BAR0. The offsets are the same so the driver must account for * any base address difference. */ @@ -2378,7 +2355,7 @@ struct wqe_common { #define wqe_rcvoxid_WORD word9 uint32_t word10; #define wqe_ebde_cnt_SHIFT 0 -#define wqe_ebde_cnt_MASK 0x00000007 +#define wqe_ebde_cnt_MASK 0x0000000f #define wqe_ebde_cnt_WORD word10 #define wqe_lenloc_SHIFT 7 #define wqe_lenloc_MASK 0x00000003 @@ -2570,7 +2547,6 @@ struct xmit_seq64_wqe { uint32_t relative_offset; struct wqe_rctl_dfctl wge_ctl; struct wqe_common wqe_com; /* words 6-11 */ - /* Note: word10 different REVISIT */ uint32_t xmit_len; uint32_t rsvd_12_15[3]; }; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 311671d3216f..462242dcdd0a 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -1406,6 +1406,8 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) struct lpfc_vport *vport = phba->pport; uint32_t event_data; struct Scsi_Host *shost; + uint32_t if_type; + struct lpfc_register portstat_reg; /* If the pci channel is offline, ignore possible errors, since * we cannot communicate with the pci card anyway. @@ -1422,17 +1424,49 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) /* For now, the actual action for SLI4 device handling is not * specified yet, just treated it as adaptor hardware failure */ - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "0143 SLI4 Adapter Hardware Error Data: x%x x%x\n", - phba->work_status[0], phba->work_status[1]); - event_data = FC_REG_DUMP_EVENT; shost = lpfc_shost_from_vport(vport); fc_host_post_vendor_event(shost, fc_get_event_number(), sizeof(event_data), (char *) &event_data, SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX); - lpfc_sli4_offline_eratt(phba); + if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf); + switch (if_type) { + case LPFC_SLI_INTF_IF_TYPE_0: + lpfc_sli4_offline_eratt(phba); + break; + case LPFC_SLI_INTF_IF_TYPE_2: + portstat_reg.word0 = + readl(phba->sli4_hba.u.if_type2.STATUSregaddr); + + if (bf_get(lpfc_sliport_status_oti, &portstat_reg)) { + /* TODO: Register for Overtemp async events. */ + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "2889 Port Overtemperature event, " + "taking port\n"); + spin_lock_irq(&phba->hbalock); + phba->over_temp_state = HBA_OVER_TEMP; + spin_unlock_irq(&phba->hbalock); + lpfc_sli4_offline_eratt(phba); + return; + } + if (bf_get(lpfc_sliport_status_rn, &portstat_reg)) { + /* + * TODO: Attempt port recovery via a port reset. + * When fully implemented, the driver should + * attempt to recover the port here and return. + * For now, log an error and take the port offline. + */ + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "2887 Port Error: Attempting " + "Port Recovery\n"); + } + lpfc_sli4_offline_eratt(phba); + break; + case LPFC_SLI_INTF_IF_TYPE_1: + default: + break; + } } /** @@ -2982,63 +3016,6 @@ lpfc_sli4_fcf_redisc_wait_tmo(unsigned long ptr) lpfc_worker_wake_up(phba); } -/** - * lpfc_sli4_fw_cfg_check - Read the firmware config and verify FCoE support - * @phba: pointer to lpfc hba data structure. - * - * This function uses the QUERY_FW_CFG mailbox command to determine if the - * firmware loaded supports FCoE. A return of zero indicates that the mailbox - * was successful and the firmware supports FCoE. Any other return indicates - * a error. It is assumed that this function will be called before interrupts - * are enabled. - **/ -static int -lpfc_sli4_fw_cfg_check(struct lpfc_hba *phba) -{ - int rc = 0; - LPFC_MBOXQ_t *mboxq; - struct lpfc_mbx_query_fw_cfg *query_fw_cfg; - uint32_t length; - uint32_t shdr_status, shdr_add_status; - - mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); - if (!mboxq) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "2621 Failed to allocate mbox for " - "query firmware config cmd\n"); - return -ENOMEM; - } - query_fw_cfg = &mboxq->u.mqe.un.query_fw_cfg; - length = (sizeof(struct lpfc_mbx_query_fw_cfg) - - sizeof(struct lpfc_sli4_cfg_mhdr)); - lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON, - LPFC_MBOX_OPCODE_QUERY_FW_CFG, - length, LPFC_SLI4_MBX_EMBED); - rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); - /* The IOCTL status is embedded in the mailbox subheader. */ - shdr_status = bf_get(lpfc_mbox_hdr_status, - &query_fw_cfg->header.cfg_shdr.response); - shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, - &query_fw_cfg->header.cfg_shdr.response); - if (shdr_status || shdr_add_status || rc != MBX_SUCCESS) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "2622 Query Firmware Config failed " - "mbx status x%x, status x%x add_status x%x\n", - rc, shdr_status, shdr_add_status); - return -EINVAL; - } - if (!bf_get(lpfc_function_mode_fcoe_i, query_fw_cfg)) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "2623 FCoE Function not supported by firmware. " - "Function mode = %08x\n", - query_fw_cfg->function_mode); - return -EINVAL; - } - if (rc != MBX_TIMEOUT) - mempool_free(mboxq, phba->mbox_mem_pool); - return 0; -} - /** * lpfc_sli4_parse_latt_fault - Parse sli4 link-attention link fault code * @phba: pointer to lpfc hba data structure. @@ -4268,6 +4245,14 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) if (rc) return -ENOMEM; + /* IF Type 2 ports get initialized now. */ + if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == + LPFC_SLI_INTF_IF_TYPE_2) { + rc = lpfc_pci_function_reset(phba); + if (unlikely(rc)) + return -ENODEV; + } + /* Create the bootstrap mailbox command */ rc = lpfc_create_bootstrap_mbox(phba); if (unlikely(rc)) @@ -4278,19 +4263,18 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) if (unlikely(rc)) goto out_free_bsmbx; - rc = lpfc_sli4_fw_cfg_check(phba); - if (unlikely(rc)) - goto out_free_bsmbx; - /* Set up the hba's configuration parameters. */ rc = lpfc_sli4_read_config(phba); if (unlikely(rc)) goto out_free_bsmbx; - /* Perform a function reset */ - rc = lpfc_pci_function_reset(phba); - if (unlikely(rc)) - goto out_free_bsmbx; + /* IF Type 0 ports get initialized now. */ + if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == + LPFC_SLI_INTF_IF_TYPE_0) { + rc = lpfc_pci_function_reset(phba); + if (unlikely(rc)) + goto out_free_bsmbx; + } mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); @@ -5388,49 +5372,51 @@ lpfc_sli_pci_mem_unset(struct lpfc_hba *phba) int lpfc_sli4_post_status_check(struct lpfc_hba *phba) { - struct lpfc_register sta_reg, uerrlo_reg, uerrhi_reg; - int i, port_error = -ENODEV; + struct lpfc_register portsmphr_reg, uerrlo_reg, uerrhi_reg; + struct lpfc_register reg_data; + int i, port_error = 0; + uint32_t if_type; - if (!phba->sli4_hba.STAregaddr) + if (!phba->sli4_hba.PSMPHRregaddr) return -ENODEV; /* Wait up to 30 seconds for the SLI Port POST done and ready */ for (i = 0; i < 3000; i++) { - sta_reg.word0 = readl(phba->sli4_hba.STAregaddr); - /* Encounter fatal POST error, break out */ - if (bf_get(lpfc_hst_state_perr, &sta_reg)) { + portsmphr_reg.word0 = readl(phba->sli4_hba.PSMPHRregaddr); + if (bf_get(lpfc_port_smphr_perr, &portsmphr_reg)) { + /* Port has a fatal POST error, break out */ port_error = -ENODEV; break; } - if (LPFC_POST_STAGE_ARMFW_READY == - bf_get(lpfc_hst_state_port_status, &sta_reg)) { - port_error = 0; + if (LPFC_POST_STAGE_PORT_READY == + bf_get(lpfc_port_smphr_port_status, &portsmphr_reg)) break; - } msleep(10); } - if (port_error) + /* + * If there was a port error during POST, then don't proceed with + * other register reads as the data may not be valid. Just exit. + */ + if (port_error) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "1408 Failure HBA POST Status: sta_reg=0x%x, " - "perr=x%x, sfi=x%x, nip=x%x, ipc=x%x, xrom=x%x, " - "dl=x%x, pstatus=x%x\n", sta_reg.word0, - bf_get(lpfc_hst_state_perr, &sta_reg), - bf_get(lpfc_hst_state_sfi, &sta_reg), - bf_get(lpfc_hst_state_nip, &sta_reg), - bf_get(lpfc_hst_state_ipc, &sta_reg), - bf_get(lpfc_hst_state_xrom, &sta_reg), - bf_get(lpfc_hst_state_dl, &sta_reg), - bf_get(lpfc_hst_state_port_status, &sta_reg)); - - /* Log device information */ - phba->sli4_hba.sli_intf.word0 = readl(phba->sli4_hba.SLIINTFregaddr); - if (bf_get(lpfc_sli_intf_valid, - &phba->sli4_hba.sli_intf) == LPFC_SLI_INTF_VALID) { + "1408 Port Failed POST - portsmphr=0x%x, " + "perr=x%x, sfi=x%x, nip=x%x, ipc=x%x, scr1=x%x, " + "scr2=x%x, hscratch=x%x, pstatus=x%x\n", + portsmphr_reg.word0, + bf_get(lpfc_port_smphr_perr, &portsmphr_reg), + bf_get(lpfc_port_smphr_sfi, &portsmphr_reg), + bf_get(lpfc_port_smphr_nip, &portsmphr_reg), + bf_get(lpfc_port_smphr_ipc, &portsmphr_reg), + bf_get(lpfc_port_smphr_scr1, &portsmphr_reg), + bf_get(lpfc_port_smphr_scr2, &portsmphr_reg), + bf_get(lpfc_port_smphr_host_scratch, &portsmphr_reg), + bf_get(lpfc_port_smphr_port_status, &portsmphr_reg)); + } else { lpfc_printf_log(phba, KERN_INFO, LOG_INIT, - "2534 Device Info: ChipType=0x%x, SliRev=0x%x, " - "IFType=0x%x, SLIHint_1=0x%x, SLIHint_2=0x%x, " - "FT=0x%x\n", + "2534 Device Info: SLIFamily=0x%x, " + "SLIRev=0x%x, IFType=0x%x, SLIHint_1=0x%x, " + "SLIHint_2=0x%x, FT=0x%x\n", bf_get(lpfc_sli_intf_sli_family, &phba->sli4_hba.sli_intf), bf_get(lpfc_sli_intf_slirev, @@ -5443,48 +5429,126 @@ lpfc_sli4_post_status_check(struct lpfc_hba *phba) &phba->sli4_hba.sli_intf), bf_get(lpfc_sli_intf_func_type, &phba->sli4_hba.sli_intf)); + /* + * Check for other Port errors during the initialization + * process. Fail the load if the port did not come up + * correctly. + */ + if_type = bf_get(lpfc_sli_intf_if_type, + &phba->sli4_hba.sli_intf); + switch (if_type) { + case LPFC_SLI_INTF_IF_TYPE_0: + phba->sli4_hba.ue_mask_lo = + readl(phba->sli4_hba.u.if_type0.UEMASKLOregaddr); + phba->sli4_hba.ue_mask_hi = + readl(phba->sli4_hba.u.if_type0.UEMASKHIregaddr); + uerrlo_reg.word0 = + readl(phba->sli4_hba.u.if_type0.UERRLOregaddr); + uerrhi_reg.word0 = + readl(phba->sli4_hba.u.if_type0.UERRHIregaddr); + if ((~phba->sli4_hba.ue_mask_lo & uerrlo_reg.word0) || + (~phba->sli4_hba.ue_mask_hi & uerrhi_reg.word0)) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "1422 Unrecoverable Error " + "Detected during POST " + "uerr_lo_reg=0x%x, " + "uerr_hi_reg=0x%x, " + "ue_mask_lo_reg=0x%x, " + "ue_mask_hi_reg=0x%x\n", + uerrlo_reg.word0, + uerrhi_reg.word0, + phba->sli4_hba.ue_mask_lo, + phba->sli4_hba.ue_mask_hi); + port_error = -ENODEV; + } + break; + case LPFC_SLI_INTF_IF_TYPE_2: + /* Final checks. The port status should be clean. */ + reg_data.word0 = + readl(phba->sli4_hba.u.if_type2.STATUSregaddr); + if (bf_get(lpfc_sliport_status_err, ®_data)) { + phba->work_status[0] = + readl(phba->sli4_hba.u.if_type2. + ERR1regaddr); + phba->work_status[1] = + readl(phba->sli4_hba.u.if_type2. + ERR2regaddr); + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "2888 Port Error Detected " + "during POST: " + "port status reg 0x%x, " + "port_smphr reg 0x%x, " + "error 1=0x%x, error 2=0x%x\n", + reg_data.word0, + portsmphr_reg.word0, + phba->work_status[0], + phba->work_status[1]); + port_error = -ENODEV; + } + break; + case LPFC_SLI_INTF_IF_TYPE_1: + default: + break; + } } - - phba->sli4_hba.ue_mask_lo = readl(phba->sli4_hba.UEMASKLOregaddr); - phba->sli4_hba.ue_mask_hi = readl(phba->sli4_hba.UEMASKHIregaddr); - /* With uncoverable error, log the error message and return error */ - uerrlo_reg.word0 = readl(phba->sli4_hba.UERRLOregaddr); - uerrhi_reg.word0 = readl(phba->sli4_hba.UERRHIregaddr); - if ((~phba->sli4_hba.ue_mask_lo & uerrlo_reg.word0) || - (~phba->sli4_hba.ue_mask_hi & uerrhi_reg.word0)) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "1422 HBA Unrecoverable error: " - "uerr_lo_reg=0x%x, uerr_hi_reg=0x%x, " - "ue_mask_lo_reg=0x%x, ue_mask_hi_reg=0x%x\n", - uerrlo_reg.word0, uerrhi_reg.word0, - phba->sli4_hba.ue_mask_lo, - phba->sli4_hba.ue_mask_hi); - return -ENODEV; - } - return port_error; } /** * lpfc_sli4_bar0_register_memmap - Set up SLI4 BAR0 register memory map. * @phba: pointer to lpfc hba data structure. + * @if_type: The SLI4 interface type getting configured. * * This routine is invoked to set up SLI4 BAR0 PCI config space register * memory map. **/ static void -lpfc_sli4_bar0_register_memmap(struct lpfc_hba *phba) -{ - phba->sli4_hba.UERRLOregaddr = phba->sli4_hba.conf_regs_memmap_p + - LPFC_UERR_STATUS_LO; - phba->sli4_hba.UERRHIregaddr = phba->sli4_hba.conf_regs_memmap_p + - LPFC_UERR_STATUS_HI; - phba->sli4_hba.UEMASKLOregaddr = phba->sli4_hba.conf_regs_memmap_p + - LPFC_UE_MASK_LO; - phba->sli4_hba.UEMASKHIregaddr = phba->sli4_hba.conf_regs_memmap_p + - LPFC_UE_MASK_HI; - phba->sli4_hba.SLIINTFregaddr = phba->sli4_hba.conf_regs_memmap_p + - LPFC_SLI_INTF; +lpfc_sli4_bar0_register_memmap(struct lpfc_hba *phba, uint32_t if_type) +{ + switch (if_type) { + case LPFC_SLI_INTF_IF_TYPE_0: + phba->sli4_hba.u.if_type0.UERRLOregaddr = + phba->sli4_hba.conf_regs_memmap_p + LPFC_UERR_STATUS_LO; + phba->sli4_hba.u.if_type0.UERRHIregaddr = + phba->sli4_hba.conf_regs_memmap_p + LPFC_UERR_STATUS_HI; + phba->sli4_hba.u.if_type0.UEMASKLOregaddr = + phba->sli4_hba.conf_regs_memmap_p + LPFC_UE_MASK_LO; + phba->sli4_hba.u.if_type0.UEMASKHIregaddr = + phba->sli4_hba.conf_regs_memmap_p + LPFC_UE_MASK_HI; + phba->sli4_hba.SLIINTFregaddr = + phba->sli4_hba.conf_regs_memmap_p + LPFC_SLI_INTF; + break; + case LPFC_SLI_INTF_IF_TYPE_2: + phba->sli4_hba.u.if_type2.ERR1regaddr = + phba->sli4_hba.conf_regs_memmap_p + LPFC_SLIPORT_ERR_1; + phba->sli4_hba.u.if_type2.ERR2regaddr = + phba->sli4_hba.conf_regs_memmap_p + LPFC_SLIPORT_ERR_2; + phba->sli4_hba.u.if_type2.CTRLregaddr = + phba->sli4_hba.conf_regs_memmap_p + LPFC_SLIPORT_CNTRL; + phba->sli4_hba.u.if_type2.STATUSregaddr = + phba->sli4_hba.conf_regs_memmap_p + LPFC_SLIPORT_STATUS; + phba->sli4_hba.SLIINTFregaddr = + phba->sli4_hba.conf_regs_memmap_p + LPFC_SLI_INTF; + phba->sli4_hba.PSMPHRregaddr = + phba->sli4_hba.conf_regs_memmap_p + LPFC_SLIPORT_IF2_SMPHR; + phba->sli4_hba.RQDBregaddr = + phba->sli4_hba.conf_regs_memmap_p + LPFC_RQ_DOORBELL; + phba->sli4_hba.WQDBregaddr = + phba->sli4_hba.conf_regs_memmap_p + LPFC_WQ_DOORBELL; + phba->sli4_hba.EQCQDBregaddr = + phba->sli4_hba.conf_regs_memmap_p + LPFC_EQCQ_DOORBELL; + phba->sli4_hba.MQDBregaddr = + phba->sli4_hba.conf_regs_memmap_p + LPFC_MQ_DOORBELL; + phba->sli4_hba.BMBXregaddr = + phba->sli4_hba.conf_regs_memmap_p + LPFC_BMBX; + break; + case LPFC_SLI_INTF_IF_TYPE_1: + default: + dev_printk(KERN_ERR, &phba->pcidev->dev, + "FATAL - unsupported SLI4 interface type - %d\n", + if_type); + break; + } } /** @@ -5497,16 +5561,14 @@ lpfc_sli4_bar0_register_memmap(struct lpfc_hba *phba) static void lpfc_sli4_bar1_register_memmap(struct lpfc_hba *phba) { - - phba->sli4_hba.STAregaddr = phba->sli4_hba.ctrl_regs_memmap_p + - LPFC_HST_STATE; + phba->sli4_hba.PSMPHRregaddr = phba->sli4_hba.ctrl_regs_memmap_p + + LPFC_SLIPORT_IF0_SMPHR; phba->sli4_hba.ISRregaddr = phba->sli4_hba.ctrl_regs_memmap_p + - LPFC_HST_ISR0; + LPFC_HST_ISR0; phba->sli4_hba.IMRregaddr = phba->sli4_hba.ctrl_regs_memmap_p + - LPFC_HST_IMR0; + LPFC_HST_IMR0; phba->sli4_hba.ISCRregaddr = phba->sli4_hba.ctrl_regs_memmap_p + - LPFC_HST_ISCR0; - return; + LPFC_HST_ISCR0; } /** @@ -5746,11 +5808,12 @@ lpfc_sli4_read_config(struct lpfc_hba *phba) } /** - * lpfc_dev_endian_order_setup - Notify the port of the host's endian order. + * lpfc_setup_endian_order - Write endian order to an SLI4 if_type 0 port. * @phba: pointer to lpfc hba data structure. * - * This routine is invoked to setup the host-side endian order to the - * HBA consistent with the SLI-4 interface spec. + * This routine is invoked to setup the port-side endian order when + * the port if_type is 0. This routine has no function for other + * if_types. * * Return codes * 0 - successful @@ -5761,34 +5824,44 @@ static int lpfc_setup_endian_order(struct lpfc_hba *phba) { LPFC_MBOXQ_t *mboxq; - uint32_t rc = 0; + uint32_t if_type, rc = 0; uint32_t endian_mb_data[2] = {HOST_ENDIAN_LOW_WORD0, HOST_ENDIAN_HIGH_WORD1}; - mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); - if (!mboxq) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "0492 Unable to allocate memory for issuing " - "SLI_CONFIG_SPECIAL mailbox command\n"); - return -ENOMEM; - } + if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf); + switch (if_type) { + case LPFC_SLI_INTF_IF_TYPE_0: + mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, + GFP_KERNEL); + if (!mboxq) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "0492 Unable to allocate memory for " + "issuing SLI_CONFIG_SPECIAL mailbox " + "command\n"); + return -ENOMEM; + } - /* - * The SLI4_CONFIG_SPECIAL mailbox command requires the first two - * words to contain special data values and no other data. - */ - memset(mboxq, 0, sizeof(LPFC_MBOXQ_t)); - memcpy(&mboxq->u.mqe, &endian_mb_data, sizeof(endian_mb_data)); - rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); - if (rc != MBX_SUCCESS) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "0493 SLI_CONFIG_SPECIAL mailbox failed with " - "status x%x\n", - rc); - rc = -EIO; + /* + * The SLI4_CONFIG_SPECIAL mailbox command requires the first + * two words to contain special data values and no other data. + */ + memset(mboxq, 0, sizeof(LPFC_MBOXQ_t)); + memcpy(&mboxq->u.mqe, &endian_mb_data, sizeof(endian_mb_data)); + rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); + if (rc != MBX_SUCCESS) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "0493 SLI_CONFIG_SPECIAL mailbox " + "failed with status x%x\n", + rc); + rc = -EIO; + } + mempool_free(mboxq, phba->mbox_mem_pool); + break; + case LPFC_SLI_INTF_IF_TYPE_2: + case LPFC_SLI_INTF_IF_TYPE_1: + default: + break; } - - mempool_free(mboxq, phba->mbox_mem_pool); return rc; } @@ -6620,36 +6693,124 @@ int lpfc_pci_function_reset(struct lpfc_hba *phba) { LPFC_MBOXQ_t *mboxq; - uint32_t rc = 0; + uint32_t rc = 0, if_type; uint32_t shdr_status, shdr_add_status; + uint32_t rdy_chk, num_resets = 0, reset_again = 0; union lpfc_sli4_cfg_shdr *shdr; + struct lpfc_register reg_data; - mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); - if (!mboxq) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "0494 Unable to allocate memory for issuing " - "SLI_FUNCTION_RESET mailbox command\n"); - return -ENOMEM; - } + if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf); + switch (if_type) { + case LPFC_SLI_INTF_IF_TYPE_0: + mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, + GFP_KERNEL); + if (!mboxq) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "0494 Unable to allocate memory for " + "issuing SLI_FUNCTION_RESET mailbox " + "command\n"); + return -ENOMEM; + } - /* Set up PCI function reset SLI4_CONFIG mailbox-ioctl command */ - lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON, - LPFC_MBOX_OPCODE_FUNCTION_RESET, 0, - LPFC_SLI4_MBX_EMBED); - rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); - shdr = (union lpfc_sli4_cfg_shdr *) - &mboxq->u.mqe.un.sli4_config.header.cfg_shdr; - shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); - shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); - if (rc != MBX_TIMEOUT) - mempool_free(mboxq, phba->mbox_mem_pool); - if (shdr_status || shdr_add_status || rc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "0495 SLI_FUNCTION_RESET mailbox failed with " - "status x%x add_status x%x, mbx status x%x\n", - shdr_status, shdr_add_status, rc); - rc = -ENXIO; + /* Setup PCI function reset mailbox-ioctl command */ + lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON, + LPFC_MBOX_OPCODE_FUNCTION_RESET, 0, + LPFC_SLI4_MBX_EMBED); + rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); + shdr = (union lpfc_sli4_cfg_shdr *) + &mboxq->u.mqe.un.sli4_config.header.cfg_shdr; + shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); + shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, + &shdr->response); + if (rc != MBX_TIMEOUT) + mempool_free(mboxq, phba->mbox_mem_pool); + if (shdr_status || shdr_add_status || rc) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "0495 SLI_FUNCTION_RESET mailbox " + "failed with status x%x add_status x%x," + " mbx status x%x\n", + shdr_status, shdr_add_status, rc); + rc = -ENXIO; + } + break; + case LPFC_SLI_INTF_IF_TYPE_2: + for (num_resets = 0; + num_resets < MAX_IF_TYPE_2_RESETS; + num_resets++) { + reg_data.word0 = 0; + bf_set(lpfc_sliport_ctrl_end, ®_data, + LPFC_SLIPORT_LITTLE_ENDIAN); + bf_set(lpfc_sliport_ctrl_ip, ®_data, + LPFC_SLIPORT_INIT_PORT); + writel(reg_data.word0, phba->sli4_hba.u.if_type2. + CTRLregaddr); + + /* + * Poll the Port Status Register and wait for RDY for + * up to 10 seconds. If the port doesn't respond, treat + * it as an error. If the port responds with RN, start + * the loop again. + */ + for (rdy_chk = 0; rdy_chk < 1000; rdy_chk++) { + reg_data.word0 = + readl(phba->sli4_hba.u.if_type2. + STATUSregaddr); + if (bf_get(lpfc_sliport_status_rdy, ®_data)) + break; + if (bf_get(lpfc_sliport_status_rn, ®_data)) { + reset_again++; + break; + } + msleep(10); + } + + /* + * If the port responds to the init request with + * reset needed, delay for a bit and restart the loop. + */ + if (reset_again) { + msleep(10); + reset_again = 0; + continue; + } + + /* Detect any port errors. */ + reg_data.word0 = readl(phba->sli4_hba.u.if_type2. + STATUSregaddr); + if ((bf_get(lpfc_sliport_status_err, ®_data)) || + (rdy_chk >= 1000)) { + phba->work_status[0] = readl( + phba->sli4_hba.u.if_type2.ERR1regaddr); + phba->work_status[1] = readl( + phba->sli4_hba.u.if_type2.ERR2regaddr); + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "2890 Port Error Detected " + "during Port Reset: " + "port status reg 0x%x, " + "error 1=0x%x, error 2=0x%x\n", + reg_data.word0, + phba->work_status[0], + phba->work_status[1]); + rc = -ENODEV; + } + + /* + * Terminate the outer loop provided the Port indicated + * ready within 10 seconds. + */ + if (rdy_chk < 1000) + break; + } + break; + case LPFC_SLI_INTF_IF_TYPE_1: + default: + break; } + + /* Catch the not-ready port failure after a port reset. */ + if (num_resets >= MAX_IF_TYPE_2_RESETS) + rc = -ENODEV; + return rc; } @@ -6740,6 +6901,7 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba) struct pci_dev *pdev; unsigned long bar0map_len, bar1map_len, bar2map_len; int error = -ENODEV; + uint32_t if_type; /* Obtain PCI device reference */ if (!phba->pcidev) @@ -6756,61 +6918,105 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba) } } - /* Get the bus address of SLI4 device Bar0, Bar1, and Bar2 and the - * number of bytes required by each mapping. They are actually - * mapping to the PCI BAR regions 0 or 1, 2, and 4 by the SLI4 device. + /* + * The BARs and register set definitions and offset locations are + * dependent on the if_type. + */ + if (pci_read_config_dword(pdev, LPFC_SLI_INTF, + &phba->sli4_hba.sli_intf.word0)) { + return error; + } + + /* There is no SLI3 failback for SLI4 devices. */ + if (bf_get(lpfc_sli_intf_valid, &phba->sli4_hba.sli_intf) != + LPFC_SLI_INTF_VALID) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "2894 SLI_INTF reg contents invalid " + "sli_intf reg 0x%x\n", + phba->sli4_hba.sli_intf.word0); + return error; + } + + if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf); + /* + * Get the bus address of SLI4 device Bar regions and the + * number of bytes required by each mapping. The mapping of the + * particular PCI BARs regions is dependent on the type of + * SLI4 device. */ if (pci_resource_start(pdev, 0)) { phba->pci_bar0_map = pci_resource_start(pdev, 0); bar0map_len = pci_resource_len(pdev, 0); + + /* + * Map SLI4 PCI Config Space Register base to a kernel virtual + * addr + */ + phba->sli4_hba.conf_regs_memmap_p = + ioremap(phba->pci_bar0_map, bar0map_len); + if (!phba->sli4_hba.conf_regs_memmap_p) { + dev_printk(KERN_ERR, &pdev->dev, + "ioremap failed for SLI4 PCI config " + "registers.\n"); + goto out; + } + /* Set up BAR0 PCI config space register memory map */ + lpfc_sli4_bar0_register_memmap(phba, if_type); } else { phba->pci_bar0_map = pci_resource_start(pdev, 1); bar0map_len = pci_resource_len(pdev, 1); - } - phba->pci_bar1_map = pci_resource_start(pdev, 2); - bar1map_len = pci_resource_len(pdev, 2); - - phba->pci_bar2_map = pci_resource_start(pdev, 4); - bar2map_len = pci_resource_len(pdev, 4); - - /* Map SLI4 PCI Config Space Register base to a kernel virtual addr */ - phba->sli4_hba.conf_regs_memmap_p = + if (if_type == LPFC_SLI_INTF_IF_TYPE_2) { + dev_printk(KERN_ERR, &pdev->dev, + "FATAL - No BAR0 mapping for SLI4, if_type 2\n"); + goto out; + } + phba->sli4_hba.conf_regs_memmap_p = ioremap(phba->pci_bar0_map, bar0map_len); - if (!phba->sli4_hba.conf_regs_memmap_p) { - dev_printk(KERN_ERR, &pdev->dev, - "ioremap failed for SLI4 PCI config registers.\n"); - goto out; + if (!phba->sli4_hba.conf_regs_memmap_p) { + dev_printk(KERN_ERR, &pdev->dev, + "ioremap failed for SLI4 PCI config " + "registers.\n"); + goto out; + } + lpfc_sli4_bar0_register_memmap(phba, if_type); } - /* Map SLI4 HBA Control Register base to a kernel virtual address. */ - phba->sli4_hba.ctrl_regs_memmap_p = + if (pci_resource_start(pdev, 2)) { + /* + * Map SLI4 if type 0 HBA Control Register base to a kernel + * virtual address and setup the registers. + */ + phba->pci_bar1_map = pci_resource_start(pdev, 2); + bar1map_len = pci_resource_len(pdev, 2); + phba->sli4_hba.ctrl_regs_memmap_p = ioremap(phba->pci_bar1_map, bar1map_len); - if (!phba->sli4_hba.ctrl_regs_memmap_p) { - dev_printk(KERN_ERR, &pdev->dev, + if (!phba->sli4_hba.ctrl_regs_memmap_p) { + dev_printk(KERN_ERR, &pdev->dev, "ioremap failed for SLI4 HBA control registers.\n"); - goto out_iounmap_conf; + goto out_iounmap_conf; + } + lpfc_sli4_bar1_register_memmap(phba); } - /* Map SLI4 HBA Doorbell Register base to a kernel virtual address. */ - phba->sli4_hba.drbl_regs_memmap_p = + if (pci_resource_start(pdev, 4)) { + /* + * Map SLI4 if type 0 HBA Doorbell Register base to a kernel + * virtual address and setup the registers. + */ + phba->pci_bar2_map = pci_resource_start(pdev, 4); + bar2map_len = pci_resource_len(pdev, 4); + phba->sli4_hba.drbl_regs_memmap_p = ioremap(phba->pci_bar2_map, bar2map_len); - if (!phba->sli4_hba.drbl_regs_memmap_p) { - dev_printk(KERN_ERR, &pdev->dev, + if (!phba->sli4_hba.drbl_regs_memmap_p) { + dev_printk(KERN_ERR, &pdev->dev, "ioremap failed for SLI4 HBA doorbell registers.\n"); - goto out_iounmap_ctrl; + goto out_iounmap_ctrl; + } + error = lpfc_sli4_bar2_register_memmap(phba, LPFC_VF0); + if (error) + goto out_iounmap_all; } - /* Set up BAR0 PCI config space register memory map */ - lpfc_sli4_bar0_register_memmap(phba); - - /* Set up BAR1 register memory map */ - lpfc_sli4_bar1_register_memmap(phba); - - /* Set up BAR2 register memory map */ - error = lpfc_sli4_bar2_register_memmap(phba, LPFC_VF0); - if (error) - goto out_iounmap_all; - return 0; out_iounmap_all: @@ -8424,7 +8630,11 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) "0451 Configure interrupt mode (%d) " "failed active interrupt test.\n", intr_mode); - /* Unset the preivous SLI-4 HBA setup */ + /* Unset the previous SLI-4 HBA setup. */ + /* + * TODO: Is this operation compatible with IF TYPE 2 + * devices? All port state is deleted and cleared. + */ lpfc_sli4_unset_hba(phba); /* Try next level of interrupt mode */ cfg_mode = --intr_mode; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 8df959ea9669..d6f3b83f3219 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -4690,6 +4690,10 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) struct lpfc_vport *vport = phba->pport; struct lpfc_dmabuf *mp; + /* + * TODO: Why does this routine execute these task in a different + * order from probe? + */ /* Perform a PCI function reset to start from clean */ rc = lpfc_pci_function_reset(phba); if (unlikely(rc)) @@ -8439,29 +8443,66 @@ static int lpfc_sli4_eratt_read(struct lpfc_hba *phba) { uint32_t uerr_sta_hi, uerr_sta_lo; + uint32_t if_type, portsmphr; + struct lpfc_register portstat_reg; - /* For now, use the SLI4 device internal unrecoverable error + /* + * For now, use the SLI4 device internal unrecoverable error * registers for error attention. This can be changed later. */ - uerr_sta_lo = readl(phba->sli4_hba.UERRLOregaddr); - uerr_sta_hi = readl(phba->sli4_hba.UERRHIregaddr); - if ((~phba->sli4_hba.ue_mask_lo & uerr_sta_lo) || - (~phba->sli4_hba.ue_mask_hi & uerr_sta_hi)) { + if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf); + switch (if_type) { + case LPFC_SLI_INTF_IF_TYPE_0: + uerr_sta_lo = readl(phba->sli4_hba.u.if_type0.UERRLOregaddr); + uerr_sta_hi = readl(phba->sli4_hba.u.if_type0.UERRHIregaddr); + if ((~phba->sli4_hba.ue_mask_lo & uerr_sta_lo) || + (~phba->sli4_hba.ue_mask_hi & uerr_sta_hi)) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "1423 HBA Unrecoverable error: " + "uerr_lo_reg=0x%x, uerr_hi_reg=0x%x, " + "ue_mask_lo_reg=0x%x, " + "ue_mask_hi_reg=0x%x\n", + uerr_sta_lo, uerr_sta_hi, + phba->sli4_hba.ue_mask_lo, + phba->sli4_hba.ue_mask_hi); + phba->work_status[0] = uerr_sta_lo; + phba->work_status[1] = uerr_sta_hi; + phba->work_ha |= HA_ERATT; + phba->hba_flag |= HBA_ERATT_HANDLED; + return 1; + } + break; + case LPFC_SLI_INTF_IF_TYPE_2: + portstat_reg.word0 = + readl(phba->sli4_hba.u.if_type2.STATUSregaddr); + portsmphr = readl(phba->sli4_hba.PSMPHRregaddr); + if (bf_get(lpfc_sliport_status_err, &portstat_reg)) { + phba->work_status[0] = + readl(phba->sli4_hba.u.if_type2.ERR1regaddr); + phba->work_status[1] = + readl(phba->sli4_hba.u.if_type2.ERR2regaddr); + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "2885 Port Error Detected: " + "port status reg 0x%x, " + "port smphr reg 0x%x, " + "error 1=0x%x, error 2=0x%x\n", + portstat_reg.word0, + portsmphr, + phba->work_status[0], + phba->work_status[1]); + phba->work_ha |= HA_ERATT; + phba->hba_flag |= HBA_ERATT_HANDLED; + return 1; + } + break; + case LPFC_SLI_INTF_IF_TYPE_1: + default: lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "1423 HBA Unrecoverable error: " - "uerr_lo_reg=0x%x, uerr_hi_reg=0x%x, " - "ue_mask_lo_reg=0x%x, ue_mask_hi_reg=0x%x\n", - uerr_sta_lo, uerr_sta_hi, - phba->sli4_hba.ue_mask_lo, - phba->sli4_hba.ue_mask_hi); - phba->work_status[0] = uerr_sta_lo; - phba->work_status[1] = uerr_sta_hi; - /* Set the driver HA work bitmap */ - phba->work_ha |= HA_ERATT; - /* Indicate polling handles this ERATT */ - phba->hba_flag |= HBA_ERATT_HANDLED; + "2886 HBA Error Attention on unsupported " + "if type %d.", if_type); return 1; } + return 0; } @@ -8516,7 +8557,7 @@ lpfc_sli_check_eratt(struct lpfc_hba *phba) ha_copy = lpfc_sli_eratt_read(phba); break; case LPFC_SLI_REV4: - /* Read devcie Uncoverable Error (UERR) registers */ + /* Read device Uncoverable Error (UERR) registers */ ha_copy = lpfc_sli4_eratt_read(phba); break; default: diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index f96eae51d07c..eb0fedfbf370 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -369,23 +369,39 @@ struct lpfc_sli4_hba { PCI BAR1, control registers */ void __iomem *drbl_regs_memmap_p; /* Kernel memory mapped address for PCI BAR2, doorbell registers */ - /* BAR0 PCI config space register memory map */ - void __iomem *UERRLOregaddr; /* Address to UERR_STATUS_LO register */ - void __iomem *UERRHIregaddr; /* Address to UERR_STATUS_HI register */ - void __iomem *UEMASKLOregaddr; /* Address to UE_MASK_LO register */ - void __iomem *UEMASKHIregaddr; /* Address to UE_MASK_HI register */ - void __iomem *SLIINTFregaddr; /* Address to SLI_INTF register */ - /* BAR1 FCoE function CSR register memory map */ - void __iomem *STAregaddr; /* Address to HST_STATE register */ - void __iomem *ISRregaddr; /* Address to HST_ISR register */ - void __iomem *IMRregaddr; /* Address to HST_IMR register */ - void __iomem *ISCRregaddr; /* Address to HST_ISCR register */ - /* BAR2 VF-0 doorbell register memory map */ - void __iomem *RQDBregaddr; /* Address to RQ_DOORBELL register */ - void __iomem *WQDBregaddr; /* Address to WQ_DOORBELL register */ - void __iomem *EQCQDBregaddr; /* Address to EQCQ_DOORBELL register */ - void __iomem *MQDBregaddr; /* Address to MQ_DOORBELL register */ - void __iomem *BMBXregaddr; /* Address to BootStrap MBX register */ + union { + struct { + /* IF Type 0, BAR 0 PCI cfg space reg mem map */ + void __iomem *UERRLOregaddr; + void __iomem *UERRHIregaddr; + void __iomem *UEMASKLOregaddr; + void __iomem *UEMASKHIregaddr; + } if_type0; + struct { + /* IF Type 2, BAR 0 PCI cfg space reg mem map. */ + void __iomem *STATUSregaddr; + void __iomem *CTRLregaddr; + void __iomem *ERR1regaddr; + void __iomem *ERR2regaddr; + } if_type2; + } u; + + /* IF type 0, BAR1 and if type 2, Bar 0 CSR register memory map */ + void __iomem *PSMPHRregaddr; + + /* Well-known SLI INTF register memory map. */ + void __iomem *SLIINTFregaddr; + + /* IF type 0, BAR 1 function CSR register memory map */ + void __iomem *ISRregaddr; /* HST_ISR register */ + void __iomem *IMRregaddr; /* HST_IMR register */ + void __iomem *ISCRregaddr; /* HST_ISCR register */ + /* IF type 0, BAR 0 and if type 2, BAR 0 doorbell register memory map */ + void __iomem *RQDBregaddr; /* RQ_DOORBELL register */ + void __iomem *WQDBregaddr; /* WQ_DOORBELL register */ + void __iomem *EQCQDBregaddr; /* EQCQ_DOORBELL register */ + void __iomem *MQDBregaddr; /* MQ_DOORBELL register */ + void __iomem *BMBXregaddr; /* BootStrap MBX register */ uint32_t ue_mask_lo; uint32_t ue_mask_hi; -- cgit v1.2.3-59-g8ed1b From 4042629e426da5ff0c793276a61103bd3f6b2183 Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 15 Dec 2010 17:58:10 -0500 Subject: [SCSI] lpfc 8.3.20: Updates to FC discovery commands Updated commands used for ELS to utilize VPI Allocate RPI at node creation time and pass in ELS commnads. Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_bsg.c | 16 ++++++++++----- drivers/scsi/lpfc/lpfc_crtn.h | 2 +- drivers/scsi/lpfc/lpfc_disc.h | 2 +- drivers/scsi/lpfc/lpfc_els.c | 19 ++++++++---------- drivers/scsi/lpfc/lpfc_hbadisc.c | 40 ++++++++++++++++++-------------------- drivers/scsi/lpfc/lpfc_mbox.c | 12 ++++-------- drivers/scsi/lpfc/lpfc_nportdisc.c | 16 +++++---------- drivers/scsi/lpfc/lpfc_sli.c | 13 ------------- drivers/scsi/lpfc/lpfc_sli4.h | 1 - 9 files changed, 49 insertions(+), 72 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 3330d7951b42..0dd43bb91618 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -1619,7 +1619,7 @@ job_error: * This function obtains a remote port login id so the diag loopback test * can send and receive its own unsolicited CT command. **/ -static int lpfcdiag_loop_self_reg(struct lpfc_hba *phba, uint16_t * rpi) +static int lpfcdiag_loop_self_reg(struct lpfc_hba *phba, uint16_t *rpi) { LPFC_MBOXQ_t *mbox; struct lpfc_dmabuf *dmabuff; @@ -1629,10 +1629,14 @@ static int lpfcdiag_loop_self_reg(struct lpfc_hba *phba, uint16_t * rpi) if (!mbox) return -ENOMEM; + if (phba->sli_rev == LPFC_SLI_REV4) + *rpi = lpfc_sli4_alloc_rpi(phba); status = lpfc_reg_rpi(phba, 0, phba->pport->fc_myDID, - (uint8_t *)&phba->pport->fc_sparam, mbox, 0); + (uint8_t *)&phba->pport->fc_sparam, mbox, *rpi); if (status) { mempool_free(mbox, phba->mbox_mem_pool); + if (phba->sli_rev == LPFC_SLI_REV4) + lpfc_sli4_free_rpi(phba, *rpi); return -ENOMEM; } @@ -1646,6 +1650,8 @@ static int lpfcdiag_loop_self_reg(struct lpfc_hba *phba, uint16_t * rpi) kfree(dmabuff); if (status != MBX_TIMEOUT) mempool_free(mbox, phba->mbox_mem_pool); + if (phba->sli_rev == LPFC_SLI_REV4) + lpfc_sli4_free_rpi(phba, *rpi); return -ENODEV; } @@ -1682,8 +1688,9 @@ static int lpfcdiag_loop_self_unreg(struct lpfc_hba *phba, uint16_t rpi) mempool_free(mbox, phba->mbox_mem_pool); return -EIO; } - mempool_free(mbox, phba->mbox_mem_pool); + if (phba->sli_rev == LPFC_SLI_REV4) + lpfc_sli4_free_rpi(phba, rpi); return 0; } @@ -2080,7 +2087,7 @@ lpfc_bsg_diag_test(struct fc_bsg_job *job) uint32_t size; uint32_t full_size; size_t segment_len = 0, segment_offset = 0, current_offset = 0; - uint16_t rpi; + uint16_t rpi = 0; struct lpfc_iocbq *cmdiocbq, *rspiocbq; IOCB_t *cmd, *rsp; struct lpfc_sli_ct_request *ctreq; @@ -2167,7 +2174,6 @@ lpfc_bsg_diag_test(struct fc_bsg_job *job) sg_copy_to_buffer(job->request_payload.sg_list, job->request_payload.sg_cnt, ptr, size); - rc = lpfcdiag_loop_self_reg(phba, &rpi); if (rc) goto loopback_test_exit; diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 9b95c50ba704..17fde522c84a 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -40,7 +40,7 @@ int lpfc_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *, int); void lpfc_read_config(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_read_lnk_stat(struct lpfc_hba *, LPFC_MBOXQ_t *); int lpfc_reg_rpi(struct lpfc_hba *, uint16_t, uint32_t, uint8_t *, - LPFC_MBOXQ_t *, uint32_t); + LPFC_MBOXQ_t *, uint16_t); void lpfc_set_var(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t); void lpfc_unreg_login(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *); void lpfc_unreg_did(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *); diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index 2f73252d15f0..1d84b63fccad 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h @@ -153,7 +153,7 @@ struct lpfc_node_rrq { #define NLP_NODEV_REMOVE 0x08000000 /* Defer removal till discovery ends */ #define NLP_TARGET_REMOVE 0x10000000 /* Target remove in process */ #define NLP_SC_REQ 0x20000000 /* Target requires authentication */ -#define NLP_RPI_VALID 0x80000000 /* nlp_rpi is valid */ +#define NLP_RPI_REGISTERED 0x80000000 /* nlp_rpi is valid */ /* ndlp usage management macros */ #define NLP_CHK_NODE_ACT(ndlp) (((ndlp)->nlp_usg_map \ diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 0705ad86538f..c62d567cc845 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -375,7 +375,8 @@ lpfc_issue_fabric_reglogin(struct lpfc_vport *vport) err = 4; goto fail; } - rc = lpfc_reg_rpi(phba, vport->vpi, Fabric_DID, (uint8_t *)sp, mbox, 0); + rc = lpfc_reg_rpi(phba, vport->vpi, Fabric_DID, (uint8_t *)sp, mbox, + ndlp->nlp_rpi); if (rc) { err = 5; goto fail_free_mbox; @@ -1023,7 +1024,9 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, if (sp->cmn.fcphHigh < FC_PH3) sp->cmn.fcphHigh = FC_PH3; - if (phba->sli_rev == LPFC_SLI_REV4) { + if ((phba->sli_rev == LPFC_SLI_REV4) && + (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == + LPFC_SLI_INTF_IF_TYPE_0)) { elsiocb->iocb.ulpCt_h = ((SLI4_CT_FCFI >> 1) & 1); elsiocb->iocb.ulpCt_l = (SLI4_CT_FCFI & 1); /* FLOGI needs to be 3 for WQE FCFI */ @@ -3318,14 +3321,6 @@ lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1); struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2; - /* - * This routine is used to register and unregister in previous SLI - * modes. - */ - if ((pmb->u.mb.mbxCommand == MBX_UNREG_LOGIN) && - (phba->sli_rev == LPFC_SLI_REV4)) - lpfc_sli4_free_rpi(phba, pmb->u.mb.un.varUnregLogin.rpi); - pmb->context1 = NULL; pmb->context2 = NULL; @@ -7090,7 +7085,9 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, icmd->un.elsreq64.myID = 0; icmd->un.elsreq64.fl = 1; - if (phba->sli_rev == LPFC_SLI_REV4) { + if ((phba->sli_rev == LPFC_SLI_REV4) && + (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == + LPFC_SLI_INTF_IF_TYPE_0)) { /* FDISC needs to be 1 for WQE VPI */ elsiocb->iocb.ulpCt_h = (SLI4_CT_VPI >> 1) & 1; elsiocb->iocb.ulpCt_l = SLI4_CT_VPI & 1 ; diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 91fa65906173..f9f160ab2ee9 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -3102,8 +3102,8 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND) ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND; - if (ndlp->nlp_flag & NLP_IGNR_REG_CMPL || - ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE) { + if (ndlp->nlp_flag & NLP_IGNR_REG_CMPL || + ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE) { /* We rcvd a rscn after issuing this * mbox reg login, we may have cycled * back through the state and be @@ -3115,10 +3115,6 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) spin_lock_irq(shost->host_lock); ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL; spin_unlock_irq(shost->host_lock); - if (phba->sli_rev == LPFC_SLI_REV4) - lpfc_sli4_free_rpi(phba, - pmb->u.mb.un.varRegLogin.rpi); - } else /* Good status, call state machine */ lpfc_disc_state_machine(vport, ndlp, pmb, @@ -3428,7 +3424,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) } ndlp->nlp_rpi = mb->un.varWords[0]; - ndlp->nlp_flag |= NLP_RPI_VALID; + ndlp->nlp_flag |= NLP_RPI_REGISTERED; ndlp->nlp_type |= NLP_FABRIC; lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); @@ -3502,7 +3498,7 @@ out: } ndlp->nlp_rpi = mb->un.varWords[0]; - ndlp->nlp_flag |= NLP_RPI_VALID; + ndlp->nlp_flag |= NLP_RPI_REGISTERED; ndlp->nlp_type |= NLP_FABRIC; lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); @@ -3835,6 +3831,8 @@ lpfc_initialize_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, NLP_INT_NODE_ACT(ndlp); atomic_set(&ndlp->cmd_pending, 0); ndlp->cmd_qdepth = vport->cfg_tgt_queue_depth; + if (vport->phba->sli_rev == LPFC_SLI_REV4) + ndlp->nlp_rpi = lpfc_sli4_alloc_rpi(vport->phba); } struct lpfc_nodelist * @@ -4048,7 +4046,7 @@ lpfc_no_rpi(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) * by firmware with a no rpi error. */ psli = &phba->sli; - if (ndlp->nlp_flag & NLP_RPI_VALID) { + if (ndlp->nlp_flag & NLP_RPI_REGISTERED) { /* Now process each ring */ for (i = 0; i < psli->num_rings; i++) { pring = &psli->ring[i]; @@ -4096,7 +4094,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) LPFC_MBOXQ_t *mbox; int rc; - if (ndlp->nlp_flag & NLP_RPI_VALID) { + if (ndlp->nlp_flag & NLP_RPI_REGISTERED) { mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (mbox) { lpfc_unreg_login(phba, vport->vpi, ndlp->nlp_rpi, mbox); @@ -4108,8 +4106,9 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) } lpfc_no_rpi(phba, ndlp); - ndlp->nlp_rpi = 0; - ndlp->nlp_flag &= ~NLP_RPI_VALID; + if (phba->sli_rev != LPFC_SLI_REV4) + ndlp->nlp_rpi = 0; + ndlp->nlp_flag &= ~NLP_RPI_REGISTERED; ndlp->nlp_flag &= ~NLP_NPR_ADISC; return 1; } @@ -4141,7 +4140,7 @@ lpfc_unreg_hba_rpis(struct lpfc_hba *phba) shost = lpfc_shost_from_vport(vports[i]); spin_lock_irq(shost->host_lock); list_for_each_entry(ndlp, &vports[i]->fc_nodes, nlp_listp) { - if (ndlp->nlp_flag & NLP_RPI_VALID) { + if (ndlp->nlp_flag & NLP_RPI_REGISTERED) { /* The mempool_alloc might sleep */ spin_unlock_irq(shost->host_lock); lpfc_unreg_rpi(vports[i], ndlp); @@ -4270,9 +4269,6 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) kfree(mp); } list_del(&mb->list); - if (phba->sli_rev == LPFC_SLI_REV4) - lpfc_sli4_free_rpi(phba, - mb->u.mb.un.varRegLogin.rpi); mempool_free(mb, phba->mbox_mem_pool); /* We shall not invoke the lpfc_nlp_put to decrement * the ndlp reference count as we are in the process @@ -4314,15 +4310,15 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) lpfc_cancel_retry_delay_tmo(vport, ndlp); if ((ndlp->nlp_flag & NLP_DEFER_RM) && - !(ndlp->nlp_flag & NLP_REG_LOGIN_SEND) && - !(ndlp->nlp_flag & NLP_RPI_VALID)) { + !(ndlp->nlp_flag & NLP_REG_LOGIN_SEND) && + !(ndlp->nlp_flag & NLP_RPI_REGISTERED)) { /* For this case we need to cleanup the default rpi * allocated by the firmware. */ if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL)) != NULL) { rc = lpfc_reg_rpi(phba, vport->vpi, ndlp->nlp_DID, - (uint8_t *) &vport->fc_sparam, mbox, 0); + (uint8_t *) &vport->fc_sparam, mbox, ndlp->nlp_rpi); if (rc) { mempool_free(mbox, phba->mbox_mem_pool); } @@ -5060,7 +5056,7 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) pmb->context2 = NULL; ndlp->nlp_rpi = mb->un.varWords[0]; - ndlp->nlp_flag |= NLP_RPI_VALID; + ndlp->nlp_flag |= NLP_RPI_REGISTERED; ndlp->nlp_type |= NLP_FABRIC; lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); @@ -5184,6 +5180,8 @@ lpfc_nlp_release(struct kref *kref) spin_lock_irqsave(&phba->ndlp_lock, flags); NLP_CLR_NODE_ACT(ndlp); spin_unlock_irqrestore(&phba->ndlp_lock, flags); + if (phba->sli_rev == LPFC_SLI_REV4) + lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi); /* free ndlp memory for final ndlp release */ if (NLP_CHK_FREE_REQ(ndlp)) { @@ -5354,7 +5352,7 @@ lpfc_fcf_inuse(struct lpfc_hba *phba) "logged in\n", ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag); - if (ndlp->nlp_flag & NLP_RPI_VALID) + if (ndlp->nlp_flag & NLP_RPI_REGISTERED) ret = 1; } } diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index b1dab92628ee..23403c650207 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -710,7 +710,7 @@ lpfc_read_lnk_stat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) * @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. + * @rpi: the rpi to use in the registration (usually only used for SLI4. * * 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 @@ -729,7 +729,7 @@ lpfc_read_lnk_stat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) **/ int lpfc_reg_rpi(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, uint16_t rpi) { MAILBOX_t *mb = &pmb->u.mb; uint8_t *sparam; @@ -739,17 +739,13 @@ lpfc_reg_rpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t did, mb->un.varRegLogin.rpi = 0; if (phba->sli_rev == LPFC_SLI_REV4) { - mb->un.varRegLogin.rpi = lpfc_sli4_alloc_rpi(phba); + mb->un.varRegLogin.rpi = rpi; if (mb->un.varRegLogin.rpi == LPFC_RPI_ALLOC_ERROR) return 1; } - mb->un.varRegLogin.vpi = vpi + phba->vpi_base; mb->un.varRegLogin.did = did; - mb->un.varWords[30] = flag; /* Set flag to issue action on cmpl */ - mb->mbxOwner = OWN_HOST; - /* Get a buffer to hold NPorts Service Parameters */ mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL); if (mp) @@ -760,7 +756,7 @@ lpfc_reg_rpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t did, /* REG_LOGIN: no buffers */ lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX, "0302 REG_LOGIN: no buffers, VPI:%d DID:x%x, " - "flag x%x\n", vpi, did, flag); + "rpi x%x\n", vpi, did, rpi); return (1); } INIT_LIST_HEAD(&mp->list); diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index bccc9c66fa37..d85a7423a694 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -386,7 +386,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, goto out; rc = lpfc_reg_rpi(phba, vport->vpi, icmd->un.rcvels.remoteID, - (uint8_t *) sp, mbox, 0); + (uint8_t *) sp, mbox, ndlp->nlp_rpi); if (rc) { mempool_free(mbox, phba->mbox_mem_pool); goto out; @@ -632,7 +632,7 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) { struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - if (!(ndlp->nlp_flag & NLP_RPI_VALID)) { + if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED)) { ndlp->nlp_flag &= ~NLP_NPR_ADISC; return 0; } @@ -968,7 +968,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, lpfc_unreg_rpi(vport, ndlp); if (lpfc_reg_rpi(phba, vport->vpi, irsp->un.elsreq64.remoteID, - (uint8_t *) sp, mbox, 0) == 0) { + (uint8_t *) sp, mbox, ndlp->nlp_rpi) == 0) { switch (ndlp->nlp_DID) { case NameServer_DID: mbox->mbox_cmpl = lpfc_mbx_cmpl_ns_reg_login; @@ -1338,12 +1338,6 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport, list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) { if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) && (ndlp == (struct lpfc_nodelist *) mb->context2)) { - if (phba->sli_rev == LPFC_SLI_REV4) { - spin_unlock_irq(&phba->hbalock); - lpfc_sli4_free_rpi(phba, - mb->u.mb.un.varRegLogin.rpi); - spin_lock_irq(&phba->hbalock); - } mp = (struct lpfc_dmabuf *) (mb->context1); if (mp) { __lpfc_mbuf_free(phba, mp->virt, mp->phys); @@ -1426,7 +1420,7 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport, } ndlp->nlp_rpi = mb->un.varWords[0]; - ndlp->nlp_flag |= NLP_RPI_VALID; + ndlp->nlp_flag |= NLP_RPI_REGISTERED; /* Only if we are not a fabric nport do we issue PRLI */ if (!(ndlp->nlp_type & NLP_FABRIC)) { @@ -2027,7 +2021,7 @@ lpfc_cmpl_reglogin_npr_node(struct lpfc_vport *vport, if (!mb->mbxStatus) { ndlp->nlp_rpi = mb->un.varWords[0]; - ndlp->nlp_flag |= NLP_RPI_VALID; + ndlp->nlp_flag |= NLP_RPI_REGISTERED; } else { if (ndlp->nlp_flag & NLP_NODEV_REMOVE) { lpfc_drop_node(vport, ndlp); diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index d6f3b83f3219..e98e792ab045 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -2116,11 +2116,6 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) kfree(mp); } - if ((pmb->u.mb.mbxCommand == MBX_UNREG_LOGIN) && - (phba->sli_rev == LPFC_SLI_REV4) && - (pmb->u.mb.un.varUnregLogin.rsvd1 == 0x0)) - lpfc_sli4_free_rpi(phba, pmb->u.mb.un.varUnregLogin.rpi); - /* * If a REG_LOGIN succeeded after node is destroyed or node * is in re-discovery driver need to cleanup the RPI. @@ -6426,11 +6421,6 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, bf_set(els_req64_vf, &wqe->els_req, 0); /* And a VFID for word 12 */ bf_set(els_req64_vfid, &wqe->els_req, 0); - /* - * Set ct field to 3, indicates that the context_tag field - * contains the FCFI and remote N_Port_ID is - * in word 5. - */ ct = ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l); bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com, iocbq->iocb.ulpContext); @@ -13372,9 +13362,6 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport) while (!list_empty(&mbox_cmd_list)) { list_remove_head(&mbox_cmd_list, mb, LPFC_MBOXQ_t, list); if (mb->u.mb.mbxCommand == MBX_REG_LOGIN64) { - if (phba->sli_rev == LPFC_SLI_REV4) - __lpfc_sli4_free_rpi(phba, - mb->u.mb.un.varRegLogin.rpi); mp = (struct lpfc_dmabuf *) (mb->context1); if (mp) { __lpfc_mbuf_free(phba, mp->virt, mp->phys); diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index eb0fedfbf370..c7217d579e0f 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -551,7 +551,6 @@ int lpfc_sli4_post_all_rpi_hdrs(struct lpfc_hba *); struct lpfc_rpi_hdr *lpfc_sli4_create_rpi_hdr(struct lpfc_hba *); void lpfc_sli4_remove_rpi_hdrs(struct lpfc_hba *); int lpfc_sli4_alloc_rpi(struct lpfc_hba *); -void __lpfc_sli4_free_rpi(struct lpfc_hba *, int); void lpfc_sli4_free_rpi(struct lpfc_hba *, int); void lpfc_sli4_remove_rpis(struct lpfc_hba *); void lpfc_sli4_async_event_proc(struct lpfc_hba *); -- cgit v1.2.3-59-g8ed1b From 774342844f368a0c3ba907f192d844ae337d01aa Mon Sep 17 00:00:00 2001 From: James Smart Date: Wed, 15 Dec 2010 17:58:20 -0500 Subject: [SCSI] lpfc 8.3.20: Update lpfc driver version to 8.3.20 Signed-off-by: Alex Iannicelli Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 10511c58f4d9..386cf92de492 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -18,7 +18,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "8.3.19" +#define LPFC_DRIVER_VERSION "8.3.20" #define LPFC_DRIVER_NAME "lpfc" #define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp" #define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp" -- cgit v1.2.3-59-g8ed1b From a0b89872b305bd0f6f5af1dd26274a3f057a2303 Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 16 Dec 2010 13:00:58 -0600 Subject: [SCSI] hpsa: do not consider firmware revision when looking for device changes. The firmware may have been updated, in which case, it's the same device, and in that case, we do not want to remove and add the device, we want to let it continue as is. Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 9 --------- drivers/scsi/hpsa.h | 1 - 2 files changed, 10 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index a6dea08664fc..a2408e591770 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -641,11 +641,6 @@ static void fixup_botched_add(struct ctlr_info *h, static inline int device_is_the_same(struct hpsa_scsi_dev_t *dev1, struct hpsa_scsi_dev_t *dev2) { - if ((is_logical_dev_addr_mode(dev1->scsi3addr) || - (dev1->lun != -1 && dev2->lun != -1)) && - dev1->devtype != 0x0C) - return (memcmp(dev1, dev2, sizeof(*dev1)) == 0); - /* we compare everything except lun and target as these * are not yet assigned. Compare parts likely * to differ first @@ -660,8 +655,6 @@ static inline int device_is_the_same(struct hpsa_scsi_dev_t *dev1, return 0; if (memcmp(dev1->vendor, dev2->vendor, sizeof(dev1->vendor)) != 0) return 0; - if (memcmp(dev1->revision, dev2->revision, sizeof(dev1->revision)) != 0) - return 0; if (dev1->devtype != dev2->devtype) return 0; if (dev1->raid_level != dev2->raid_level) @@ -1477,8 +1470,6 @@ static int hpsa_update_device_info(struct ctlr_info *h, sizeof(this_device->vendor)); memcpy(this_device->model, &inq_buff[16], sizeof(this_device->model)); - memcpy(this_device->revision, &inq_buff[32], - sizeof(this_device->revision)); memset(this_device->device_id, 0, sizeof(this_device->device_id)); hpsa_get_device_id(h, scsi3addr, this_device->device_id, diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index a203ef65cb50..19586e189f0f 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -45,7 +45,6 @@ struct hpsa_scsi_dev_t { unsigned char device_id[16]; /* from inquiry pg. 0x83 */ unsigned char vendor[8]; /* bytes 8-15 of inquiry data */ unsigned char model[16]; /* bytes 16-31 of inquiry data */ - unsigned char revision[4]; /* bytes 32-35 of inquiry data */ unsigned char raid_level; /* from inquiry page 0xC1 */ }; -- cgit v1.2.3-59-g8ed1b From 35dd3039e09cd46ca3a8733ff1c817bf7b7b19ce Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Thu, 16 Dec 2010 13:01:03 -0600 Subject: [SCSI] hpsa: do not consider RAID level to be part of device identity Otherwise, after doing a RAID level migration, the disk will be disruptively removed and re-added as a different disk on rescan. Signed-off-by: Stephen M. Cameron Signed-off-by: James Bottomley --- drivers/scsi/hpsa.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index a2408e591770..12deffccb8da 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -657,8 +657,6 @@ static inline int device_is_the_same(struct hpsa_scsi_dev_t *dev1, return 0; if (dev1->devtype != dev2->devtype) return 0; - if (dev1->raid_level != dev2->raid_level) - return 0; if (dev1->bus != dev2->bus) return 0; return 1; -- cgit v1.2.3-59-g8ed1b From db422318cbca55168cf965f655471dbf8be82433 Mon Sep 17 00:00:00 2001 From: Menny Hamburger Date: Thu, 16 Dec 2010 14:57:07 -0500 Subject: [SCSI] scsi_dh: propagate SCSI device deletion Currently, when scsi_dh_activate() returns with an error (e.g. SCSI_DH_NOSYS) the activate_complete callback is not called and the error is not propagated to DM mpath. When a SCSI device attached to a device handler is deleted, userland processes currently performing I/O on the device will have their I/O hang forever. - Set SCSI_DH_NOSYS error when the handler is in the process of being deleted (e.g. the SCSI device is in a SDEV_CANCEL or SDEV_DEL state). - Set SCSI_DH_DEV_OFFLINED error when device is in SDEV_OFFLINE state. - Call the activate_complete callback function directly from scsi_dh_activate if an error has been set (when either the scsi_dh internal data has already been deleted or is in the process of being deleted). The patch was tested in an iSCSI environment, RDAC H/W handler and multipath. In the following reproduction process, dd will I/O hang forever and the only way to release it will be to reboot the machine: 1) Perform I/O on a multipath device: dd if=/dev/dm-0 of=/dev/zero bs=8k count=1000000 & 2) Delete all slave SCSI devices contained in the mpath device: I) In an iSCSI environment, the easiest way to do this is by stopping iSCSI: /etc/init.d/iscsi stop II) Another way to delete the devices is by applying the following bash scriptlet: dm_devs=$(ls /sys/block/ | grep dm- | xargs) for dm_dev in $dm_devs; do devices=$(ls /sys/block/$dm_dev/slaves) for device in $devices; do echo 1 > /sys/block/$device/device/delete done done NOTE: when DM mpath's fail_path uses blk_abort_queue this scsi_dh change isn't strictly required. However, DM mpath's call to blk_abort_queue will soon be reverted because it has proven to be unsafe due to a race (between blk_abort_queue and scsi_request_fn) that can lead to list corruption. Therefore we cannot rely on blk_abort_queue via fail_path, but even if we could this scsi_dh change is still preferrable. Signed-off-by: Menny Hamburger Signed-off-by: Mike Snitzer Reviewed-by: Babu Moger Signed-off-by: James Bottomley --- drivers/scsi/device_handler/scsi_dh.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c index 6fae3d285ae7..b837c5b3c8f9 100644 --- a/drivers/scsi/device_handler/scsi_dh.c +++ b/drivers/scsi/device_handler/scsi_dh.c @@ -442,12 +442,19 @@ int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data) sdev = q->queuedata; if (sdev && sdev->scsi_dh_data) scsi_dh = sdev->scsi_dh_data->scsi_dh; - if (!scsi_dh || !get_device(&sdev->sdev_gendev)) + if (!scsi_dh || !get_device(&sdev->sdev_gendev) || + sdev->sdev_state == SDEV_CANCEL || + sdev->sdev_state == SDEV_DEL) err = SCSI_DH_NOSYS; + if (sdev->sdev_state == SDEV_OFFLINE) + err = SCSI_DH_DEV_OFFLINED; spin_unlock_irqrestore(q->queue_lock, flags); - if (err) + if (err) { + if (fn) + fn(data, err); return err; + } if (scsi_dh->activate) err = scsi_dh->activate(sdev, fn, data); -- cgit v1.2.3-59-g8ed1b From fd01a6632da253210c3dbc7814bc6eceda96623d Mon Sep 17 00:00:00 2001 From: Hillf Danton Date: Thu, 16 Dec 2010 14:26:37 -0600 Subject: [SCSI] fix the return value of scsi_target_queue_read() It seems that zero should be returned if scsi_target_is_busy(starget) is true, no matter if sdev is on the starved list. Signed-off-by: Hillf Danton Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 5b6bbaea59fe..0ed7a66cdded 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1278,11 +1278,10 @@ static inline int scsi_target_queue_ready(struct Scsi_Host *shost, } if (scsi_target_is_busy(starget)) { - if (list_empty(&sdev->starved_entry)) { + if (list_empty(&sdev->starved_entry)) list_add_tail(&sdev->starved_entry, &shost->starved_list); - return 0; - } + return 0; } /* We're OK to process the command, so we can't be starved */ -- cgit v1.2.3-59-g8ed1b From 0d49016bbab4fe9164710b1d4bbae116b89b7f7e Mon Sep 17 00:00:00 2001 From: adam radford Date: Tue, 14 Dec 2010 19:17:17 -0800 Subject: [SCSI] megaraid_sas: Rename megaraid_sas.c to megaraid_sas_base.c This patch renames megaraid_sas.c to megaraid_sas_base.c to facilitate other files in the compile. Signed-off-by: Adam Radford Signed-off-by: James Bottomley --- drivers/scsi/megaraid/Makefile | 1 + drivers/scsi/megaraid/megaraid_sas.c | 5193 ----------------------------- drivers/scsi/megaraid/megaraid_sas_base.c | 5193 +++++++++++++++++++++++++++++ 3 files changed, 5194 insertions(+), 5193 deletions(-) delete mode 100644 drivers/scsi/megaraid/megaraid_sas.c create mode 100644 drivers/scsi/megaraid/megaraid_sas_base.c diff --git a/drivers/scsi/megaraid/Makefile b/drivers/scsi/megaraid/Makefile index f469915b97c3..6613a2ceea03 100644 --- a/drivers/scsi/megaraid/Makefile +++ b/drivers/scsi/megaraid/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_MEGARAID_MM) += megaraid_mm.o obj-$(CONFIG_MEGARAID_MAILBOX) += megaraid_mbox.o obj-$(CONFIG_MEGARAID_SAS) += megaraid_sas.o +megaraid_sas-objs := megaraid_sas_base.o diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c deleted file mode 100644 index 7451bc096a01..000000000000 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ /dev/null @@ -1,5193 +0,0 @@ -/* - * - * Linux MegaRAID driver for SAS based RAID controllers - * - * Copyright (c) 2003-2005 LSI Corporation. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * FILE : megaraid_sas.c - * Version : v00.00.04.31-rc1 - * - * Authors: - * (email-id : megaraidlinux@lsi.com) - * Sreenivas Bagalkote - * Sumant Patro - * Bo Yang - * - * List of supported controllers - * - * OEM Product Name VID DID SSVID SSID - * --- ------------ --- --- ---- ---- - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include "megaraid_sas.h" - -/* - * poll_mode_io:1- schedule complete completion from q cmd - */ -static unsigned int poll_mode_io; -module_param_named(poll_mode_io, poll_mode_io, int, 0); -MODULE_PARM_DESC(poll_mode_io, - "Complete cmds from IO path, (default=0)"); - -/* - * Number of sectors per IO command - * Will be set in megasas_init_mfi if user does not provide - */ -static unsigned int max_sectors; -module_param_named(max_sectors, max_sectors, int, 0); -MODULE_PARM_DESC(max_sectors, - "Maximum number of sectors per IO command"); - -MODULE_LICENSE("GPL"); -MODULE_VERSION(MEGASAS_VERSION); -MODULE_AUTHOR("megaraidlinux@lsi.com"); -MODULE_DESCRIPTION("LSI MegaRAID SAS Driver"); - -static int megasas_transition_to_ready(struct megasas_instance *instance); -static int megasas_get_pd_list(struct megasas_instance *instance); -static int megasas_issue_init_mfi(struct megasas_instance *instance); -static int megasas_register_aen(struct megasas_instance *instance, - u32 seq_num, u32 class_locale_word); -/* - * PCI ID table for all supported controllers - */ -static struct pci_device_id megasas_pci_table[] = { - - {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064R)}, - /* xscale IOP */ - {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078R)}, - /* ppc IOP */ - {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078DE)}, - /* ppc IOP */ - {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078GEN2)}, - /* gen2*/ - {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0079GEN2)}, - /* gen2*/ - {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0073SKINNY)}, - /* skinny*/ - {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0071SKINNY)}, - /* skinny*/ - {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)}, - /* xscale IOP, vega */ - {PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)}, - /* xscale IOP */ - {} -}; - -MODULE_DEVICE_TABLE(pci, megasas_pci_table); - -static int megasas_mgmt_majorno; -static struct megasas_mgmt_info megasas_mgmt_info; -static struct fasync_struct *megasas_async_queue; -static DEFINE_MUTEX(megasas_async_queue_mutex); - -static int megasas_poll_wait_aen; -static DECLARE_WAIT_QUEUE_HEAD(megasas_poll_wait); -static u32 support_poll_for_event; -static u32 megasas_dbg_lvl; -static u32 support_device_change; - -/* define lock for aen poll */ -spinlock_t poll_aen_lock; - -static void -megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, - u8 alt_status); - -/** - * megasas_get_cmd - Get a command from the free pool - * @instance: Adapter soft state - * - * Returns a free command from the pool - */ -static struct megasas_cmd *megasas_get_cmd(struct megasas_instance - *instance) -{ - unsigned long flags; - struct megasas_cmd *cmd = NULL; - - spin_lock_irqsave(&instance->cmd_pool_lock, flags); - - if (!list_empty(&instance->cmd_pool)) { - cmd = list_entry((&instance->cmd_pool)->next, - struct megasas_cmd, list); - list_del_init(&cmd->list); - } else { - printk(KERN_ERR "megasas: Command pool empty!\n"); - } - - spin_unlock_irqrestore(&instance->cmd_pool_lock, flags); - return cmd; -} - -/** - * megasas_return_cmd - Return a cmd to free command pool - * @instance: Adapter soft state - * @cmd: Command packet to be returned to free command pool - */ -static inline void -megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) -{ - unsigned long flags; - - spin_lock_irqsave(&instance->cmd_pool_lock, flags); - - cmd->scmd = NULL; - list_add_tail(&cmd->list, &instance->cmd_pool); - - spin_unlock_irqrestore(&instance->cmd_pool_lock, flags); -} - - -/** -* The following functions are defined for xscale -* (deviceid : 1064R, PERC5) controllers -*/ - -/** - * megasas_enable_intr_xscale - Enables interrupts - * @regs: MFI register set - */ -static inline void -megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs) -{ - writel(0, &(regs)->outbound_intr_mask); - - /* Dummy readl to force pci flush */ - readl(®s->outbound_intr_mask); -} - -/** - * megasas_disable_intr_xscale -Disables interrupt - * @regs: MFI register set - */ -static inline void -megasas_disable_intr_xscale(struct megasas_register_set __iomem * regs) -{ - u32 mask = 0x1f; - writel(mask, ®s->outbound_intr_mask); - /* Dummy readl to force pci flush */ - readl(®s->outbound_intr_mask); -} - -/** - * megasas_read_fw_status_reg_xscale - returns the current FW status value - * @regs: MFI register set - */ -static u32 -megasas_read_fw_status_reg_xscale(struct megasas_register_set __iomem * regs) -{ - return readl(&(regs)->outbound_msg_0); -} -/** - * megasas_clear_interrupt_xscale - Check & clear interrupt - * @regs: MFI register set - */ -static int -megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs) -{ - u32 status; - u32 mfiStatus = 0; - /* - * Check if it is our interrupt - */ - status = readl(®s->outbound_intr_status); - - if (status & MFI_OB_INTR_STATUS_MASK) - mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE; - if (status & MFI_XSCALE_OMR0_CHANGE_INTERRUPT) - mfiStatus |= MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE; - - /* - * Clear the interrupt by writing back the same value - */ - if (mfiStatus) - writel(status, ®s->outbound_intr_status); - - /* Dummy readl to force pci flush */ - readl(®s->outbound_intr_status); - - return mfiStatus; -} - -/** - * megasas_fire_cmd_xscale - Sends command to the FW - * @frame_phys_addr : Physical address of cmd - * @frame_count : Number of frames for the command - * @regs : MFI register set - */ -static inline void -megasas_fire_cmd_xscale(struct megasas_instance *instance, - dma_addr_t frame_phys_addr, - u32 frame_count, - struct megasas_register_set __iomem *regs) -{ - unsigned long flags; - spin_lock_irqsave(&instance->hba_lock, flags); - writel((frame_phys_addr >> 3)|(frame_count), - &(regs)->inbound_queue_port); - spin_unlock_irqrestore(&instance->hba_lock, flags); -} - -/** - * megasas_adp_reset_xscale - For controller reset - * @regs: MFI register set - */ -static int -megasas_adp_reset_xscale(struct megasas_instance *instance, - struct megasas_register_set __iomem *regs) -{ - u32 i; - u32 pcidata; - writel(MFI_ADP_RESET, ®s->inbound_doorbell); - - for (i = 0; i < 3; i++) - msleep(1000); /* sleep for 3 secs */ - pcidata = 0; - pci_read_config_dword(instance->pdev, MFI_1068_PCSR_OFFSET, &pcidata); - printk(KERN_NOTICE "pcidata = %x\n", pcidata); - if (pcidata & 0x2) { - printk(KERN_NOTICE "mfi 1068 offset read=%x\n", pcidata); - pcidata &= ~0x2; - pci_write_config_dword(instance->pdev, - MFI_1068_PCSR_OFFSET, pcidata); - - for (i = 0; i < 2; i++) - msleep(1000); /* need to wait 2 secs again */ - - pcidata = 0; - pci_read_config_dword(instance->pdev, - MFI_1068_FW_HANDSHAKE_OFFSET, &pcidata); - printk(KERN_NOTICE "1068 offset handshake read=%x\n", pcidata); - if ((pcidata & 0xffff0000) == MFI_1068_FW_READY) { - printk(KERN_NOTICE "1068 offset pcidt=%x\n", pcidata); - pcidata = 0; - pci_write_config_dword(instance->pdev, - MFI_1068_FW_HANDSHAKE_OFFSET, pcidata); - } - } - return 0; -} - -/** - * megasas_check_reset_xscale - For controller reset check - * @regs: MFI register set - */ -static int -megasas_check_reset_xscale(struct megasas_instance *instance, - struct megasas_register_set __iomem *regs) -{ - u32 consumer; - consumer = *instance->consumer; - - if ((instance->adprecovery != MEGASAS_HBA_OPERATIONAL) && - (*instance->consumer == MEGASAS_ADPRESET_INPROG_SIGN)) { - return 1; - } - return 0; -} - -static struct megasas_instance_template megasas_instance_template_xscale = { - - .fire_cmd = megasas_fire_cmd_xscale, - .enable_intr = megasas_enable_intr_xscale, - .disable_intr = megasas_disable_intr_xscale, - .clear_intr = megasas_clear_intr_xscale, - .read_fw_status_reg = megasas_read_fw_status_reg_xscale, - .adp_reset = megasas_adp_reset_xscale, - .check_reset = megasas_check_reset_xscale, -}; - -/** -* This is the end of set of functions & definitions specific -* to xscale (deviceid : 1064R, PERC5) controllers -*/ - -/** -* The following functions are defined for ppc (deviceid : 0x60) -* controllers -*/ - -/** - * megasas_enable_intr_ppc - Enables interrupts - * @regs: MFI register set - */ -static inline void -megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs) -{ - writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear); - - writel(~0x80000000, &(regs)->outbound_intr_mask); - - /* Dummy readl to force pci flush */ - readl(®s->outbound_intr_mask); -} - -/** - * megasas_disable_intr_ppc - Disable interrupt - * @regs: MFI register set - */ -static inline void -megasas_disable_intr_ppc(struct megasas_register_set __iomem * regs) -{ - u32 mask = 0xFFFFFFFF; - writel(mask, ®s->outbound_intr_mask); - /* Dummy readl to force pci flush */ - readl(®s->outbound_intr_mask); -} - -/** - * megasas_read_fw_status_reg_ppc - returns the current FW status value - * @regs: MFI register set - */ -static u32 -megasas_read_fw_status_reg_ppc(struct megasas_register_set __iomem * regs) -{ - return readl(&(regs)->outbound_scratch_pad); -} - -/** - * megasas_clear_interrupt_ppc - Check & clear interrupt - * @regs: MFI register set - */ -static int -megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs) -{ - u32 status; - /* - * Check if it is our interrupt - */ - status = readl(®s->outbound_intr_status); - - if (!(status & MFI_REPLY_1078_MESSAGE_INTERRUPT)) { - return 0; - } - - /* - * Clear the interrupt by writing back the same value - */ - writel(status, ®s->outbound_doorbell_clear); - - /* Dummy readl to force pci flush */ - readl(®s->outbound_doorbell_clear); - - return 1; -} -/** - * megasas_fire_cmd_ppc - Sends command to the FW - * @frame_phys_addr : Physical address of cmd - * @frame_count : Number of frames for the command - * @regs : MFI register set - */ -static inline void -megasas_fire_cmd_ppc(struct megasas_instance *instance, - dma_addr_t frame_phys_addr, - u32 frame_count, - struct megasas_register_set __iomem *regs) -{ - unsigned long flags; - spin_lock_irqsave(&instance->hba_lock, flags); - writel((frame_phys_addr | (frame_count<<1))|1, - &(regs)->inbound_queue_port); - spin_unlock_irqrestore(&instance->hba_lock, flags); -} - -/** - * megasas_adp_reset_ppc - For controller reset - * @regs: MFI register set - */ -static int -megasas_adp_reset_ppc(struct megasas_instance *instance, - struct megasas_register_set __iomem *regs) -{ - return 0; -} - -/** - * megasas_check_reset_ppc - For controller reset check - * @regs: MFI register set - */ -static int -megasas_check_reset_ppc(struct megasas_instance *instance, - struct megasas_register_set __iomem *regs) -{ - return 0; -} -static struct megasas_instance_template megasas_instance_template_ppc = { - - .fire_cmd = megasas_fire_cmd_ppc, - .enable_intr = megasas_enable_intr_ppc, - .disable_intr = megasas_disable_intr_ppc, - .clear_intr = megasas_clear_intr_ppc, - .read_fw_status_reg = megasas_read_fw_status_reg_ppc, - .adp_reset = megasas_adp_reset_ppc, - .check_reset = megasas_check_reset_ppc, -}; - -/** - * megasas_enable_intr_skinny - Enables interrupts - * @regs: MFI register set - */ -static inline void -megasas_enable_intr_skinny(struct megasas_register_set __iomem *regs) -{ - writel(0xFFFFFFFF, &(regs)->outbound_intr_mask); - - writel(~MFI_SKINNY_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask); - - /* Dummy readl to force pci flush */ - readl(®s->outbound_intr_mask); -} - -/** - * megasas_disable_intr_skinny - Disables interrupt - * @regs: MFI register set - */ -static inline void -megasas_disable_intr_skinny(struct megasas_register_set __iomem *regs) -{ - u32 mask = 0xFFFFFFFF; - writel(mask, ®s->outbound_intr_mask); - /* Dummy readl to force pci flush */ - readl(®s->outbound_intr_mask); -} - -/** - * megasas_read_fw_status_reg_skinny - returns the current FW status value - * @regs: MFI register set - */ -static u32 -megasas_read_fw_status_reg_skinny(struct megasas_register_set __iomem *regs) -{ - return readl(&(regs)->outbound_scratch_pad); -} - -/** - * megasas_clear_interrupt_skinny - Check & clear interrupt - * @regs: MFI register set - */ -static int -megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs) -{ - u32 status; - /* - * Check if it is our interrupt - */ - status = readl(®s->outbound_intr_status); - - if (!(status & MFI_SKINNY_ENABLE_INTERRUPT_MASK)) { - return 0; - } - - /* - * Clear the interrupt by writing back the same value - */ - writel(status, ®s->outbound_intr_status); - - /* - * dummy read to flush PCI - */ - readl(®s->outbound_intr_status); - - return 1; -} - -/** - * megasas_fire_cmd_skinny - Sends command to the FW - * @frame_phys_addr : Physical address of cmd - * @frame_count : Number of frames for the command - * @regs : MFI register set - */ -static inline void -megasas_fire_cmd_skinny(struct megasas_instance *instance, - dma_addr_t frame_phys_addr, - u32 frame_count, - struct megasas_register_set __iomem *regs) -{ - unsigned long flags; - spin_lock_irqsave(&instance->hba_lock, flags); - writel(0, &(regs)->inbound_high_queue_port); - writel((frame_phys_addr | (frame_count<<1))|1, - &(regs)->inbound_low_queue_port); - spin_unlock_irqrestore(&instance->hba_lock, flags); -} - -/** - * megasas_adp_reset_skinny - For controller reset - * @regs: MFI register set - */ -static int -megasas_adp_reset_skinny(struct megasas_instance *instance, - struct megasas_register_set __iomem *regs) -{ - return 0; -} - -/** - * megasas_check_reset_skinny - For controller reset check - * @regs: MFI register set - */ -static int -megasas_check_reset_skinny(struct megasas_instance *instance, - struct megasas_register_set __iomem *regs) -{ - return 0; -} - -static struct megasas_instance_template megasas_instance_template_skinny = { - - .fire_cmd = megasas_fire_cmd_skinny, - .enable_intr = megasas_enable_intr_skinny, - .disable_intr = megasas_disable_intr_skinny, - .clear_intr = megasas_clear_intr_skinny, - .read_fw_status_reg = megasas_read_fw_status_reg_skinny, - .adp_reset = megasas_adp_reset_skinny, - .check_reset = megasas_check_reset_skinny, -}; - - -/** -* The following functions are defined for gen2 (deviceid : 0x78 0x79) -* controllers -*/ - -/** - * megasas_enable_intr_gen2 - Enables interrupts - * @regs: MFI register set - */ -static inline void -megasas_enable_intr_gen2(struct megasas_register_set __iomem *regs) -{ - writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear); - - /* write ~0x00000005 (4 & 1) to the intr mask*/ - writel(~MFI_GEN2_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask); - - /* Dummy readl to force pci flush */ - readl(®s->outbound_intr_mask); -} - -/** - * megasas_disable_intr_gen2 - Disables interrupt - * @regs: MFI register set - */ -static inline void -megasas_disable_intr_gen2(struct megasas_register_set __iomem *regs) -{ - u32 mask = 0xFFFFFFFF; - writel(mask, ®s->outbound_intr_mask); - /* Dummy readl to force pci flush */ - readl(®s->outbound_intr_mask); -} - -/** - * megasas_read_fw_status_reg_gen2 - returns the current FW status value - * @regs: MFI register set - */ -static u32 -megasas_read_fw_status_reg_gen2(struct megasas_register_set __iomem *regs) -{ - return readl(&(regs)->outbound_scratch_pad); -} - -/** - * megasas_clear_interrupt_gen2 - Check & clear interrupt - * @regs: MFI register set - */ -static int -megasas_clear_intr_gen2(struct megasas_register_set __iomem *regs) -{ - u32 status; - u32 mfiStatus = 0; - /* - * Check if it is our interrupt - */ - status = readl(®s->outbound_intr_status); - - if (status & MFI_GEN2_ENABLE_INTERRUPT_MASK) { - mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE; - } - if (status & MFI_G2_OUTBOUND_DOORBELL_CHANGE_INTERRUPT) { - mfiStatus |= MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE; - } - - /* - * Clear the interrupt by writing back the same value - */ - if (mfiStatus) - writel(status, ®s->outbound_doorbell_clear); - - /* Dummy readl to force pci flush */ - readl(®s->outbound_intr_status); - - return mfiStatus; -} -/** - * megasas_fire_cmd_gen2 - Sends command to the FW - * @frame_phys_addr : Physical address of cmd - * @frame_count : Number of frames for the command - * @regs : MFI register set - */ -static inline void -megasas_fire_cmd_gen2(struct megasas_instance *instance, - dma_addr_t frame_phys_addr, - u32 frame_count, - struct megasas_register_set __iomem *regs) -{ - unsigned long flags; - spin_lock_irqsave(&instance->hba_lock, flags); - writel((frame_phys_addr | (frame_count<<1))|1, - &(regs)->inbound_queue_port); - spin_unlock_irqrestore(&instance->hba_lock, flags); -} - -/** - * megasas_adp_reset_gen2 - For controller reset - * @regs: MFI register set - */ -static int -megasas_adp_reset_gen2(struct megasas_instance *instance, - struct megasas_register_set __iomem *reg_set) -{ - u32 retry = 0 ; - u32 HostDiag; - - writel(0, ®_set->seq_offset); - writel(4, ®_set->seq_offset); - writel(0xb, ®_set->seq_offset); - writel(2, ®_set->seq_offset); - writel(7, ®_set->seq_offset); - writel(0xd, ®_set->seq_offset); - msleep(1000); - - HostDiag = (u32)readl(®_set->host_diag); - - while ( !( HostDiag & DIAG_WRITE_ENABLE) ) { - msleep(100); - HostDiag = (u32)readl(®_set->host_diag); - printk(KERN_NOTICE "RESETGEN2: retry=%x, hostdiag=%x\n", - retry, HostDiag); - - if (retry++ >= 100) - return 1; - - } - - printk(KERN_NOTICE "ADP_RESET_GEN2: HostDiag=%x\n", HostDiag); - - writel((HostDiag | DIAG_RESET_ADAPTER), ®_set->host_diag); - - ssleep(10); - - HostDiag = (u32)readl(®_set->host_diag); - while ( ( HostDiag & DIAG_RESET_ADAPTER) ) { - msleep(100); - HostDiag = (u32)readl(®_set->host_diag); - printk(KERN_NOTICE "RESET_GEN2: retry=%x, hostdiag=%x\n", - retry, HostDiag); - - if (retry++ >= 1000) - return 1; - - } - return 0; -} - -/** - * megasas_check_reset_gen2 - For controller reset check - * @regs: MFI register set - */ -static int -megasas_check_reset_gen2(struct megasas_instance *instance, - struct megasas_register_set __iomem *regs) -{ - if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) { - return 1; - } - - return 0; -} - -static struct megasas_instance_template megasas_instance_template_gen2 = { - - .fire_cmd = megasas_fire_cmd_gen2, - .enable_intr = megasas_enable_intr_gen2, - .disable_intr = megasas_disable_intr_gen2, - .clear_intr = megasas_clear_intr_gen2, - .read_fw_status_reg = megasas_read_fw_status_reg_gen2, - .adp_reset = megasas_adp_reset_gen2, - .check_reset = megasas_check_reset_gen2, -}; - -/** -* This is the end of set of functions & definitions -* specific to gen2 (deviceid : 0x78, 0x79) controllers -*/ - -/** - * megasas_issue_polled - Issues a polling command - * @instance: Adapter soft state - * @cmd: Command packet to be issued - * - * For polling, MFI requires the cmd_status to be set to 0xFF before posting. - */ -static int -megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd) -{ - int i; - u32 msecs = MFI_POLL_TIMEOUT_SECS * 1000; - - struct megasas_header *frame_hdr = &cmd->frame->hdr; - - frame_hdr->cmd_status = 0xFF; - frame_hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE; - - /* - * Issue the frame using inbound queue port - */ - instance->instancet->fire_cmd(instance, - cmd->frame_phys_addr, 0, instance->reg_set); - - /* - * Wait for cmd_status to change - */ - for (i = 0; (i < msecs) && (frame_hdr->cmd_status == 0xff); i++) { - rmb(); - msleep(1); - } - - if (frame_hdr->cmd_status == 0xff) - return -ETIME; - - return 0; -} - -/** - * megasas_issue_blocked_cmd - Synchronous wrapper around regular FW cmds - * @instance: Adapter soft state - * @cmd: Command to be issued - * - * This function waits on an event for the command to be returned from ISR. - * Max wait time is MEGASAS_INTERNAL_CMD_WAIT_TIME secs - * Used to issue ioctl commands. - */ -static int -megasas_issue_blocked_cmd(struct megasas_instance *instance, - struct megasas_cmd *cmd) -{ - cmd->cmd_status = ENODATA; - - instance->instancet->fire_cmd(instance, - cmd->frame_phys_addr, 0, instance->reg_set); - - wait_event(instance->int_cmd_wait_q, cmd->cmd_status != ENODATA); - - return 0; -} - -/** - * megasas_issue_blocked_abort_cmd - Aborts previously issued cmd - * @instance: Adapter soft state - * @cmd_to_abort: Previously issued cmd to be aborted - * - * MFI firmware can abort previously issued AEN comamnd (automatic event - * notification). The megasas_issue_blocked_abort_cmd() issues such abort - * cmd and waits for return status. - * Max wait time is MEGASAS_INTERNAL_CMD_WAIT_TIME secs - */ -static int -megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, - struct megasas_cmd *cmd_to_abort) -{ - struct megasas_cmd *cmd; - struct megasas_abort_frame *abort_fr; - - cmd = megasas_get_cmd(instance); - - if (!cmd) - return -1; - - abort_fr = &cmd->frame->abort; - - /* - * Prepare and issue the abort frame - */ - abort_fr->cmd = MFI_CMD_ABORT; - abort_fr->cmd_status = 0xFF; - abort_fr->flags = 0; - abort_fr->abort_context = cmd_to_abort->index; - abort_fr->abort_mfi_phys_addr_lo = cmd_to_abort->frame_phys_addr; - abort_fr->abort_mfi_phys_addr_hi = 0; - - cmd->sync_cmd = 1; - cmd->cmd_status = 0xFF; - - instance->instancet->fire_cmd(instance, - cmd->frame_phys_addr, 0, instance->reg_set); - - /* - * Wait for this cmd to complete - */ - wait_event(instance->abort_cmd_wait_q, cmd->cmd_status != 0xFF); - cmd->sync_cmd = 0; - - megasas_return_cmd(instance, cmd); - return 0; -} - -/** - * megasas_make_sgl32 - Prepares 32-bit SGL - * @instance: Adapter soft state - * @scp: SCSI command from the mid-layer - * @mfi_sgl: SGL to be filled in - * - * If successful, this function returns the number of SG elements. Otherwise, - * it returnes -1. - */ -static int -megasas_make_sgl32(struct megasas_instance *instance, struct scsi_cmnd *scp, - union megasas_sgl *mfi_sgl) -{ - int i; - int sge_count; - struct scatterlist *os_sgl; - - sge_count = scsi_dma_map(scp); - BUG_ON(sge_count < 0); - - if (sge_count) { - scsi_for_each_sg(scp, os_sgl, sge_count, i) { - mfi_sgl->sge32[i].length = sg_dma_len(os_sgl); - mfi_sgl->sge32[i].phys_addr = sg_dma_address(os_sgl); - } - } - return sge_count; -} - -/** - * megasas_make_sgl64 - Prepares 64-bit SGL - * @instance: Adapter soft state - * @scp: SCSI command from the mid-layer - * @mfi_sgl: SGL to be filled in - * - * If successful, this function returns the number of SG elements. Otherwise, - * it returnes -1. - */ -static int -megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, - union megasas_sgl *mfi_sgl) -{ - int i; - int sge_count; - struct scatterlist *os_sgl; - - sge_count = scsi_dma_map(scp); - BUG_ON(sge_count < 0); - - if (sge_count) { - scsi_for_each_sg(scp, os_sgl, sge_count, i) { - mfi_sgl->sge64[i].length = sg_dma_len(os_sgl); - mfi_sgl->sge64[i].phys_addr = sg_dma_address(os_sgl); - } - } - return sge_count; -} - -/** - * megasas_make_sgl_skinny - Prepares IEEE SGL - * @instance: Adapter soft state - * @scp: SCSI command from the mid-layer - * @mfi_sgl: SGL to be filled in - * - * If successful, this function returns the number of SG elements. Otherwise, - * it returnes -1. - */ -static int -megasas_make_sgl_skinny(struct megasas_instance *instance, - struct scsi_cmnd *scp, union megasas_sgl *mfi_sgl) -{ - int i; - int sge_count; - struct scatterlist *os_sgl; - - sge_count = scsi_dma_map(scp); - - if (sge_count) { - scsi_for_each_sg(scp, os_sgl, sge_count, i) { - mfi_sgl->sge_skinny[i].length = sg_dma_len(os_sgl); - mfi_sgl->sge_skinny[i].phys_addr = - sg_dma_address(os_sgl); - mfi_sgl->sge_skinny[i].flag = 0; - } - } - return sge_count; -} - - /** - * megasas_get_frame_count - Computes the number of frames - * @frame_type : type of frame- io or pthru frame - * @sge_count : number of sg elements - * - * Returns the number of frames required for numnber of sge's (sge_count) - */ - -static u32 megasas_get_frame_count(struct megasas_instance *instance, - u8 sge_count, u8 frame_type) -{ - int num_cnt; - int sge_bytes; - u32 sge_sz; - u32 frame_count=0; - - sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : - sizeof(struct megasas_sge32); - - if (instance->flag_ieee) { - sge_sz = sizeof(struct megasas_sge_skinny); - } - - /* - * Main frame can contain 2 SGEs for 64-bit SGLs and - * 3 SGEs for 32-bit SGLs for ldio & - * 1 SGEs for 64-bit SGLs and - * 2 SGEs for 32-bit SGLs for pthru frame - */ - if (unlikely(frame_type == PTHRU_FRAME)) { - if (instance->flag_ieee == 1) { - num_cnt = sge_count - 1; - } else if (IS_DMA64) - num_cnt = sge_count - 1; - else - num_cnt = sge_count - 2; - } else { - if (instance->flag_ieee == 1) { - num_cnt = sge_count - 1; - } else if (IS_DMA64) - num_cnt = sge_count - 2; - else - num_cnt = sge_count - 3; - } - - if(num_cnt>0){ - sge_bytes = sge_sz * num_cnt; - - frame_count = (sge_bytes / MEGAMFI_FRAME_SIZE) + - ((sge_bytes % MEGAMFI_FRAME_SIZE) ? 1 : 0) ; - } - /* Main frame */ - frame_count +=1; - - if (frame_count > 7) - frame_count = 8; - return frame_count; -} - -/** - * megasas_build_dcdb - Prepares a direct cdb (DCDB) command - * @instance: Adapter soft state - * @scp: SCSI command - * @cmd: Command to be prepared in - * - * This function prepares CDB commands. These are typcially pass-through - * commands to the devices. - */ -static int -megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, - struct megasas_cmd *cmd) -{ - u32 is_logical; - u32 device_id; - u16 flags = 0; - struct megasas_pthru_frame *pthru; - - is_logical = MEGASAS_IS_LOGICAL(scp); - device_id = MEGASAS_DEV_INDEX(instance, scp); - pthru = (struct megasas_pthru_frame *)cmd->frame; - - if (scp->sc_data_direction == PCI_DMA_TODEVICE) - flags = MFI_FRAME_DIR_WRITE; - else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) - flags = MFI_FRAME_DIR_READ; - else if (scp->sc_data_direction == PCI_DMA_NONE) - flags = MFI_FRAME_DIR_NONE; - - if (instance->flag_ieee == 1) { - flags |= MFI_FRAME_IEEE; - } - - /* - * Prepare the DCDB frame - */ - pthru->cmd = (is_logical) ? MFI_CMD_LD_SCSI_IO : MFI_CMD_PD_SCSI_IO; - pthru->cmd_status = 0x0; - pthru->scsi_status = 0x0; - pthru->target_id = device_id; - pthru->lun = scp->device->lun; - pthru->cdb_len = scp->cmd_len; - pthru->timeout = 0; - pthru->pad_0 = 0; - pthru->flags = flags; - pthru->data_xfer_len = scsi_bufflen(scp); - - memcpy(pthru->cdb, scp->cmnd, scp->cmd_len); - - /* - * If the command is for the tape device, set the - * pthru timeout to the os layer timeout value. - */ - if (scp->device->type == TYPE_TAPE) { - if ((scp->request->timeout / HZ) > 0xFFFF) - pthru->timeout = 0xFFFF; - else - pthru->timeout = scp->request->timeout / HZ; - } - - /* - * Construct SGL - */ - if (instance->flag_ieee == 1) { - pthru->flags |= MFI_FRAME_SGL64; - pthru->sge_count = megasas_make_sgl_skinny(instance, scp, - &pthru->sgl); - } else if (IS_DMA64) { - pthru->flags |= MFI_FRAME_SGL64; - pthru->sge_count = megasas_make_sgl64(instance, scp, - &pthru->sgl); - } else - pthru->sge_count = megasas_make_sgl32(instance, scp, - &pthru->sgl); - - if (pthru->sge_count > instance->max_num_sge) { - printk(KERN_ERR "megasas: DCDB two many SGE NUM=%x\n", - pthru->sge_count); - return 0; - } - - /* - * Sense info specific - */ - pthru->sense_len = SCSI_SENSE_BUFFERSIZE; - pthru->sense_buf_phys_addr_hi = 0; - pthru->sense_buf_phys_addr_lo = cmd->sense_phys_addr; - - /* - * Compute the total number of frames this command consumes. FW uses - * this number to pull sufficient number of frames from host memory. - */ - cmd->frame_count = megasas_get_frame_count(instance, pthru->sge_count, - PTHRU_FRAME); - - return cmd->frame_count; -} - -/** - * megasas_build_ldio - Prepares IOs to logical devices - * @instance: Adapter soft state - * @scp: SCSI command - * @cmd: Command to be prepared - * - * Frames (and accompanying SGLs) for regular SCSI IOs use this function. - */ -static int -megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, - struct megasas_cmd *cmd) -{ - u32 device_id; - u8 sc = scp->cmnd[0]; - u16 flags = 0; - struct megasas_io_frame *ldio; - - device_id = MEGASAS_DEV_INDEX(instance, scp); - ldio = (struct megasas_io_frame *)cmd->frame; - - if (scp->sc_data_direction == PCI_DMA_TODEVICE) - flags = MFI_FRAME_DIR_WRITE; - else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) - flags = MFI_FRAME_DIR_READ; - - if (instance->flag_ieee == 1) { - flags |= MFI_FRAME_IEEE; - } - - /* - * Prepare the Logical IO frame: 2nd bit is zero for all read cmds - */ - ldio->cmd = (sc & 0x02) ? MFI_CMD_LD_WRITE : MFI_CMD_LD_READ; - ldio->cmd_status = 0x0; - ldio->scsi_status = 0x0; - ldio->target_id = device_id; - ldio->timeout = 0; - ldio->reserved_0 = 0; - ldio->pad_0 = 0; - ldio->flags = flags; - ldio->start_lba_hi = 0; - ldio->access_byte = (scp->cmd_len != 6) ? scp->cmnd[1] : 0; - - /* - * 6-byte READ(0x08) or WRITE(0x0A) cdb - */ - if (scp->cmd_len == 6) { - ldio->lba_count = (u32) scp->cmnd[4]; - ldio->start_lba_lo = ((u32) scp->cmnd[1] << 16) | - ((u32) scp->cmnd[2] << 8) | (u32) scp->cmnd[3]; - - ldio->start_lba_lo &= 0x1FFFFF; - } - - /* - * 10-byte READ(0x28) or WRITE(0x2A) cdb - */ - else if (scp->cmd_len == 10) { - ldio->lba_count = (u32) scp->cmnd[8] | - ((u32) scp->cmnd[7] << 8); - ldio->start_lba_lo = ((u32) scp->cmnd[2] << 24) | - ((u32) scp->cmnd[3] << 16) | - ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5]; - } - - /* - * 12-byte READ(0xA8) or WRITE(0xAA) cdb - */ - else if (scp->cmd_len == 12) { - ldio->lba_count = ((u32) scp->cmnd[6] << 24) | - ((u32) scp->cmnd[7] << 16) | - ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9]; - - ldio->start_lba_lo = ((u32) scp->cmnd[2] << 24) | - ((u32) scp->cmnd[3] << 16) | - ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5]; - } - - /* - * 16-byte READ(0x88) or WRITE(0x8A) cdb - */ - else if (scp->cmd_len == 16) { - ldio->lba_count = ((u32) scp->cmnd[10] << 24) | - ((u32) scp->cmnd[11] << 16) | - ((u32) scp->cmnd[12] << 8) | (u32) scp->cmnd[13]; - - ldio->start_lba_lo = ((u32) scp->cmnd[6] << 24) | - ((u32) scp->cmnd[7] << 16) | - ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9]; - - ldio->start_lba_hi = ((u32) scp->cmnd[2] << 24) | - ((u32) scp->cmnd[3] << 16) | - ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5]; - - } - - /* - * Construct SGL - */ - if (instance->flag_ieee) { - ldio->flags |= MFI_FRAME_SGL64; - ldio->sge_count = megasas_make_sgl_skinny(instance, scp, - &ldio->sgl); - } else if (IS_DMA64) { - ldio->flags |= MFI_FRAME_SGL64; - ldio->sge_count = megasas_make_sgl64(instance, scp, &ldio->sgl); - } else - ldio->sge_count = megasas_make_sgl32(instance, scp, &ldio->sgl); - - if (ldio->sge_count > instance->max_num_sge) { - printk(KERN_ERR "megasas: build_ld_io: sge_count = %x\n", - ldio->sge_count); - return 0; - } - - /* - * Sense info specific - */ - ldio->sense_len = SCSI_SENSE_BUFFERSIZE; - ldio->sense_buf_phys_addr_hi = 0; - ldio->sense_buf_phys_addr_lo = cmd->sense_phys_addr; - - /* - * Compute the total number of frames this command consumes. FW uses - * this number to pull sufficient number of frames from host memory. - */ - cmd->frame_count = megasas_get_frame_count(instance, - ldio->sge_count, IO_FRAME); - - return cmd->frame_count; -} - -/** - * megasas_is_ldio - Checks if the cmd is for logical drive - * @scmd: SCSI command - * - * Called by megasas_queue_command to find out if the command to be queued - * is a logical drive command - */ -static inline int megasas_is_ldio(struct scsi_cmnd *cmd) -{ - if (!MEGASAS_IS_LOGICAL(cmd)) - return 0; - switch (cmd->cmnd[0]) { - case READ_10: - case WRITE_10: - case READ_12: - case WRITE_12: - case READ_6: - case WRITE_6: - case READ_16: - case WRITE_16: - return 1; - default: - return 0; - } -} - - /** - * megasas_dump_pending_frames - Dumps the frame address of all pending cmds - * in FW - * @instance: Adapter soft state - */ -static inline void -megasas_dump_pending_frames(struct megasas_instance *instance) -{ - struct megasas_cmd *cmd; - int i,n; - union megasas_sgl *mfi_sgl; - struct megasas_io_frame *ldio; - struct megasas_pthru_frame *pthru; - u32 sgcount; - u32 max_cmd = instance->max_fw_cmds; - - printk(KERN_ERR "\nmegasas[%d]: Dumping Frame Phys Address of all pending cmds in FW\n",instance->host->host_no); - printk(KERN_ERR "megasas[%d]: Total OS Pending cmds : %d\n",instance->host->host_no,atomic_read(&instance->fw_outstanding)); - if (IS_DMA64) - printk(KERN_ERR "\nmegasas[%d]: 64 bit SGLs were sent to FW\n",instance->host->host_no); - else - printk(KERN_ERR "\nmegasas[%d]: 32 bit SGLs were sent to FW\n",instance->host->host_no); - - printk(KERN_ERR "megasas[%d]: Pending OS cmds in FW : \n",instance->host->host_no); - for (i = 0; i < max_cmd; i++) { - cmd = instance->cmd_list[i]; - if(!cmd->scmd) - continue; - printk(KERN_ERR "megasas[%d]: Frame addr :0x%08lx : ",instance->host->host_no,(unsigned long)cmd->frame_phys_addr); - if (megasas_is_ldio(cmd->scmd)){ - ldio = (struct megasas_io_frame *)cmd->frame; - mfi_sgl = &ldio->sgl; - sgcount = ldio->sge_count; - printk(KERN_ERR "megasas[%d]: frame count : 0x%x, Cmd : 0x%x, Tgt id : 0x%x, lba lo : 0x%x, lba_hi : 0x%x, sense_buf addr : 0x%x,sge count : 0x%x\n",instance->host->host_no, cmd->frame_count,ldio->cmd,ldio->target_id, ldio->start_lba_lo,ldio->start_lba_hi,ldio->sense_buf_phys_addr_lo,sgcount); - } - else { - pthru = (struct megasas_pthru_frame *) cmd->frame; - mfi_sgl = &pthru->sgl; - sgcount = pthru->sge_count; - printk(KERN_ERR "megasas[%d]: frame count : 0x%x, Cmd : 0x%x, Tgt id : 0x%x, lun : 0x%x, cdb_len : 0x%x, data xfer len : 0x%x, sense_buf addr : 0x%x,sge count : 0x%x\n",instance->host->host_no,cmd->frame_count,pthru->cmd,pthru->target_id,pthru->lun,pthru->cdb_len , pthru->data_xfer_len,pthru->sense_buf_phys_addr_lo,sgcount); - } - if(megasas_dbg_lvl & MEGASAS_DBG_LVL){ - for (n = 0; n < sgcount; n++){ - if (IS_DMA64) - printk(KERN_ERR "megasas: sgl len : 0x%x, sgl addr : 0x%08lx ",mfi_sgl->sge64[n].length , (unsigned long)mfi_sgl->sge64[n].phys_addr) ; - else - printk(KERN_ERR "megasas: sgl len : 0x%x, sgl addr : 0x%x ",mfi_sgl->sge32[n].length , mfi_sgl->sge32[n].phys_addr) ; - } - } - printk(KERN_ERR "\n"); - } /*for max_cmd*/ - printk(KERN_ERR "\nmegasas[%d]: Pending Internal cmds in FW : \n",instance->host->host_no); - for (i = 0; i < max_cmd; i++) { - - cmd = instance->cmd_list[i]; - - if(cmd->sync_cmd == 1){ - printk(KERN_ERR "0x%08lx : ", (unsigned long)cmd->frame_phys_addr); - } - } - printk(KERN_ERR "megasas[%d]: Dumping Done.\n\n",instance->host->host_no); -} - -/** - * megasas_queue_command - Queue entry point - * @scmd: SCSI command to be queued - * @done: Callback entry point - */ -static int -megasas_queue_command_lck(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *)) -{ - u32 frame_count; - struct megasas_cmd *cmd; - struct megasas_instance *instance; - unsigned long flags; - - instance = (struct megasas_instance *) - scmd->device->host->hostdata; - - if (instance->issuepend_done == 0) - return SCSI_MLQUEUE_HOST_BUSY; - - spin_lock_irqsave(&instance->hba_lock, flags); - if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) { - spin_unlock_irqrestore(&instance->hba_lock, flags); - return SCSI_MLQUEUE_HOST_BUSY; - } - - spin_unlock_irqrestore(&instance->hba_lock, flags); - - scmd->scsi_done = done; - scmd->result = 0; - - if (MEGASAS_IS_LOGICAL(scmd) && - (scmd->device->id >= MEGASAS_MAX_LD || scmd->device->lun)) { - scmd->result = DID_BAD_TARGET << 16; - goto out_done; - } - - switch (scmd->cmnd[0]) { - case SYNCHRONIZE_CACHE: - /* - * FW takes care of flush cache on its own - * No need to send it down - */ - scmd->result = DID_OK << 16; - goto out_done; - default: - break; - } - - cmd = megasas_get_cmd(instance); - if (!cmd) - return SCSI_MLQUEUE_HOST_BUSY; - - /* - * Logical drive command - */ - if (megasas_is_ldio(scmd)) - frame_count = megasas_build_ldio(instance, scmd, cmd); - else - frame_count = megasas_build_dcdb(instance, scmd, cmd); - - if (!frame_count) - goto out_return_cmd; - - cmd->scmd = scmd; - scmd->SCp.ptr = (char *)cmd; - - /* - * Issue the command to the FW - */ - atomic_inc(&instance->fw_outstanding); - - instance->instancet->fire_cmd(instance, cmd->frame_phys_addr, - cmd->frame_count-1, instance->reg_set); - /* - * Check if we have pend cmds to be completed - */ - if (poll_mode_io && atomic_read(&instance->fw_outstanding)) - tasklet_schedule(&instance->isr_tasklet); - - - return 0; - - out_return_cmd: - megasas_return_cmd(instance, cmd); - out_done: - done(scmd); - return 0; -} - -static DEF_SCSI_QCMD(megasas_queue_command) - -static struct megasas_instance *megasas_lookup_instance(u16 host_no) -{ - int i; - - for (i = 0; i < megasas_mgmt_info.max_index; i++) { - - if ((megasas_mgmt_info.instance[i]) && - (megasas_mgmt_info.instance[i]->host->host_no == host_no)) - return megasas_mgmt_info.instance[i]; - } - - return NULL; -} - -static int megasas_slave_configure(struct scsi_device *sdev) -{ - u16 pd_index = 0; - struct megasas_instance *instance ; - - instance = megasas_lookup_instance(sdev->host->host_no); - - /* - * Don't export physical disk devices to the disk driver. - * - * FIXME: Currently we don't export them to the midlayer at all. - * That will be fixed once LSI engineers have audited the - * firmware for possible issues. - */ - if (sdev->channel < MEGASAS_MAX_PD_CHANNELS && - sdev->type == TYPE_DISK) { - pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + - sdev->id; - if (instance->pd_list[pd_index].driveState == - MR_PD_STATE_SYSTEM) { - blk_queue_rq_timeout(sdev->request_queue, - MEGASAS_DEFAULT_CMD_TIMEOUT * HZ); - return 0; - } - return -ENXIO; - } - - /* - * The RAID firmware may require extended timeouts. - */ - blk_queue_rq_timeout(sdev->request_queue, - MEGASAS_DEFAULT_CMD_TIMEOUT * HZ); - return 0; -} - -static int megasas_slave_alloc(struct scsi_device *sdev) -{ - u16 pd_index = 0; - struct megasas_instance *instance ; - instance = megasas_lookup_instance(sdev->host->host_no); - if ((sdev->channel < MEGASAS_MAX_PD_CHANNELS) && - (sdev->type == TYPE_DISK)) { - /* - * Open the OS scan to the SYSTEM PD - */ - pd_index = - (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + - sdev->id; - if ((instance->pd_list[pd_index].driveState == - MR_PD_STATE_SYSTEM) && - (instance->pd_list[pd_index].driveType == - TYPE_DISK)) { - return 0; - } - return -ENXIO; - } - return 0; -} - -static void megaraid_sas_kill_hba(struct megasas_instance *instance) -{ - if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || - (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { - writel(MFI_STOP_ADP, - &instance->reg_set->reserved_0[0]); - } else { - writel(MFI_STOP_ADP, - &instance->reg_set->inbound_doorbell); - } -} - -/** - * megasas_complete_cmd_dpc - Returns FW's controller structure - * @instance_addr: Address of adapter soft state - * - * Tasklet to complete cmds - */ -static void megasas_complete_cmd_dpc(unsigned long instance_addr) -{ - u32 producer; - u32 consumer; - u32 context; - struct megasas_cmd *cmd; - struct megasas_instance *instance = - (struct megasas_instance *)instance_addr; - unsigned long flags; - - /* If we have already declared adapter dead, donot complete cmds */ - if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR ) - return; - - spin_lock_irqsave(&instance->completion_lock, flags); - - producer = *instance->producer; - consumer = *instance->consumer; - - while (consumer != producer) { - context = instance->reply_queue[consumer]; - if (context >= instance->max_fw_cmds) { - printk(KERN_ERR "Unexpected context value %x\n", - context); - BUG(); - } - - cmd = instance->cmd_list[context]; - - megasas_complete_cmd(instance, cmd, DID_OK); - - consumer++; - if (consumer == (instance->max_fw_cmds + 1)) { - consumer = 0; - } - } - - *instance->consumer = producer; - - spin_unlock_irqrestore(&instance->completion_lock, flags); - - /* - * Check if we can restore can_queue - */ - if (instance->flag & MEGASAS_FW_BUSY - && time_after(jiffies, instance->last_time + 5 * HZ) - && atomic_read(&instance->fw_outstanding) < 17) { - - spin_lock_irqsave(instance->host->host_lock, flags); - instance->flag &= ~MEGASAS_FW_BUSY; - if ((instance->pdev->device == - PCI_DEVICE_ID_LSI_SAS0073SKINNY) || - (instance->pdev->device == - PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { - instance->host->can_queue = - instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS; - } else - instance->host->can_queue = - instance->max_fw_cmds - MEGASAS_INT_CMDS; - - spin_unlock_irqrestore(instance->host->host_lock, flags); - } -} - -static void -megasas_internal_reset_defer_cmds(struct megasas_instance *instance); - -static void -process_fw_state_change_wq(struct work_struct *work); - -void megasas_do_ocr(struct megasas_instance *instance) -{ - if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1064R) || - (instance->pdev->device == PCI_DEVICE_ID_DELL_PERC5) || - (instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR)) { - *instance->consumer = MEGASAS_ADPRESET_INPROG_SIGN; - } - instance->instancet->disable_intr(instance->reg_set); - instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT; - instance->issuepend_done = 0; - - atomic_set(&instance->fw_outstanding, 0); - megasas_internal_reset_defer_cmds(instance); - process_fw_state_change_wq(&instance->work_init); -} - -/** - * megasas_wait_for_outstanding - Wait for all outstanding cmds - * @instance: Adapter soft state - * - * This function waits for upto MEGASAS_RESET_WAIT_TIME seconds for FW to - * complete all its outstanding commands. Returns error if one or more IOs - * are pending after this time period. It also marks the controller dead. - */ -static int megasas_wait_for_outstanding(struct megasas_instance *instance) -{ - int i; - u32 reset_index; - u32 wait_time = MEGASAS_RESET_WAIT_TIME; - u8 adprecovery; - unsigned long flags; - struct list_head clist_local; - struct megasas_cmd *reset_cmd; - u32 fw_state; - u8 kill_adapter_flag; - - spin_lock_irqsave(&instance->hba_lock, flags); - adprecovery = instance->adprecovery; - spin_unlock_irqrestore(&instance->hba_lock, flags); - - if (adprecovery != MEGASAS_HBA_OPERATIONAL) { - - INIT_LIST_HEAD(&clist_local); - spin_lock_irqsave(&instance->hba_lock, flags); - list_splice_init(&instance->internal_reset_pending_q, - &clist_local); - spin_unlock_irqrestore(&instance->hba_lock, flags); - - printk(KERN_NOTICE "megasas: HBA reset wait ...\n"); - for (i = 0; i < wait_time; i++) { - msleep(1000); - spin_lock_irqsave(&instance->hba_lock, flags); - adprecovery = instance->adprecovery; - spin_unlock_irqrestore(&instance->hba_lock, flags); - if (adprecovery == MEGASAS_HBA_OPERATIONAL) - break; - } - - if (adprecovery != MEGASAS_HBA_OPERATIONAL) { - printk(KERN_NOTICE "megasas: reset: Stopping HBA.\n"); - spin_lock_irqsave(&instance->hba_lock, flags); - instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR; - spin_unlock_irqrestore(&instance->hba_lock, flags); - return FAILED; - } - - reset_index = 0; - while (!list_empty(&clist_local)) { - reset_cmd = list_entry((&clist_local)->next, - struct megasas_cmd, list); - list_del_init(&reset_cmd->list); - if (reset_cmd->scmd) { - reset_cmd->scmd->result = DID_RESET << 16; - printk(KERN_NOTICE "%d:%p reset [%02x], %#lx\n", - reset_index, reset_cmd, - reset_cmd->scmd->cmnd[0], - reset_cmd->scmd->serial_number); - - reset_cmd->scmd->scsi_done(reset_cmd->scmd); - megasas_return_cmd(instance, reset_cmd); - } else if (reset_cmd->sync_cmd) { - printk(KERN_NOTICE "megasas:%p synch cmds" - "reset queue\n", - reset_cmd); - - reset_cmd->cmd_status = ENODATA; - instance->instancet->fire_cmd(instance, - reset_cmd->frame_phys_addr, - 0, instance->reg_set); - } else { - printk(KERN_NOTICE "megasas: %p unexpected" - "cmds lst\n", - reset_cmd); - } - reset_index++; - } - - return SUCCESS; - } - - for (i = 0; i < wait_time; i++) { - - int outstanding = atomic_read(&instance->fw_outstanding); - - if (!outstanding) - break; - - if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { - printk(KERN_NOTICE "megasas: [%2d]waiting for %d " - "commands to complete\n",i,outstanding); - /* - * Call cmd completion routine. Cmd to be - * be completed directly without depending on isr. - */ - megasas_complete_cmd_dpc((unsigned long)instance); - } - - msleep(1000); - } - - i = 0; - kill_adapter_flag = 0; - do { - fw_state = instance->instancet->read_fw_status_reg( - instance->reg_set) & MFI_STATE_MASK; - if ((fw_state == MFI_STATE_FAULT) && - (instance->disableOnlineCtrlReset == 0)) { - if (i == 3) { - kill_adapter_flag = 2; - break; - } - megasas_do_ocr(instance); - kill_adapter_flag = 1; - - /* wait for 1 secs to let FW finish the pending cmds */ - msleep(1000); - } - i++; - } while (i <= 3); - - if (atomic_read(&instance->fw_outstanding) && - !kill_adapter_flag) { - if (instance->disableOnlineCtrlReset == 0) { - - megasas_do_ocr(instance); - - /* wait for 5 secs to let FW finish the pending cmds */ - for (i = 0; i < wait_time; i++) { - int outstanding = - atomic_read(&instance->fw_outstanding); - if (!outstanding) - return SUCCESS; - msleep(1000); - } - } - } - - if (atomic_read(&instance->fw_outstanding) || - (kill_adapter_flag == 2)) { - printk(KERN_NOTICE "megaraid_sas: pending cmds after reset\n"); - /* - * Send signal to FW to stop processing any pending cmds. - * The controller will be taken offline by the OS now. - */ - if ((instance->pdev->device == - PCI_DEVICE_ID_LSI_SAS0073SKINNY) || - (instance->pdev->device == - PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { - writel(MFI_STOP_ADP, - &instance->reg_set->reserved_0[0]); - } else { - writel(MFI_STOP_ADP, - &instance->reg_set->inbound_doorbell); - } - megasas_dump_pending_frames(instance); - spin_lock_irqsave(&instance->hba_lock, flags); - instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR; - spin_unlock_irqrestore(&instance->hba_lock, flags); - return FAILED; - } - - printk(KERN_NOTICE "megaraid_sas: no pending cmds after reset\n"); - - return SUCCESS; -} - -/** - * megasas_generic_reset - Generic reset routine - * @scmd: Mid-layer SCSI command - * - * This routine implements a generic reset handler for device, bus and host - * reset requests. Device, bus and host specific reset handlers can use this - * function after they do their specific tasks. - */ -static int megasas_generic_reset(struct scsi_cmnd *scmd) -{ - int ret_val; - struct megasas_instance *instance; - - instance = (struct megasas_instance *)scmd->device->host->hostdata; - - scmd_printk(KERN_NOTICE, scmd, "megasas: RESET -%ld cmd=%x retries=%x\n", - scmd->serial_number, scmd->cmnd[0], scmd->retries); - - if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) { - printk(KERN_ERR "megasas: cannot recover from previous reset " - "failures\n"); - return FAILED; - } - - ret_val = megasas_wait_for_outstanding(instance); - if (ret_val == SUCCESS) - printk(KERN_NOTICE "megasas: reset successful \n"); - else - printk(KERN_ERR "megasas: failed to do reset\n"); - - return ret_val; -} - -/** - * megasas_reset_timer - quiesce the adapter if required - * @scmd: scsi cmnd - * - * Sets the FW busy flag and reduces the host->can_queue if the - * cmd has not been completed within the timeout period. - */ -static enum -blk_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd) -{ - struct megasas_cmd *cmd = (struct megasas_cmd *)scmd->SCp.ptr; - struct megasas_instance *instance; - unsigned long flags; - - if (time_after(jiffies, scmd->jiffies_at_alloc + - (MEGASAS_DEFAULT_CMD_TIMEOUT * 2) * HZ)) { - return BLK_EH_NOT_HANDLED; - } - - instance = cmd->instance; - if (!(instance->flag & MEGASAS_FW_BUSY)) { - /* FW is busy, throttle IO */ - spin_lock_irqsave(instance->host->host_lock, flags); - - instance->host->can_queue = 16; - instance->last_time = jiffies; - instance->flag |= MEGASAS_FW_BUSY; - - spin_unlock_irqrestore(instance->host->host_lock, flags); - } - return BLK_EH_RESET_TIMER; -} - -/** - * megasas_reset_device - Device reset handler entry point - */ -static int megasas_reset_device(struct scsi_cmnd *scmd) -{ - int ret; - - /* - * First wait for all commands to complete - */ - ret = megasas_generic_reset(scmd); - - return ret; -} - -/** - * megasas_reset_bus_host - Bus & host reset handler entry point - */ -static int megasas_reset_bus_host(struct scsi_cmnd *scmd) -{ - int ret; - - /* - * First wait for all commands to complete - */ - ret = megasas_generic_reset(scmd); - - return ret; -} - -/** - * megasas_bios_param - Returns disk geometry for a disk - * @sdev: device handle - * @bdev: block device - * @capacity: drive capacity - * @geom: geometry parameters - */ -static int -megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int geom[]) -{ - int heads; - int sectors; - sector_t cylinders; - unsigned long tmp; - /* Default heads (64) & sectors (32) */ - heads = 64; - sectors = 32; - - tmp = heads * sectors; - cylinders = capacity; - - sector_div(cylinders, tmp); - - /* - * Handle extended translation size for logical drives > 1Gb - */ - - if (capacity >= 0x200000) { - heads = 255; - sectors = 63; - tmp = heads*sectors; - cylinders = capacity; - sector_div(cylinders, tmp); - } - - geom[0] = heads; - geom[1] = sectors; - geom[2] = cylinders; - - return 0; -} - -static void megasas_aen_polling(struct work_struct *work); - -/** - * megasas_service_aen - Processes an event notification - * @instance: Adapter soft state - * @cmd: AEN command completed by the ISR - * - * For AEN, driver sends a command down to FW that is held by the FW till an - * event occurs. When an event of interest occurs, FW completes the command - * that it was previously holding. - * - * This routines sends SIGIO signal to processes that have registered with the - * driver for AEN. - */ -static void -megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd) -{ - unsigned long flags; - /* - * Don't signal app if it is just an aborted previously registered aen - */ - if ((!cmd->abort_aen) && (instance->unload == 0)) { - spin_lock_irqsave(&poll_aen_lock, flags); - megasas_poll_wait_aen = 1; - spin_unlock_irqrestore(&poll_aen_lock, flags); - wake_up(&megasas_poll_wait); - kill_fasync(&megasas_async_queue, SIGIO, POLL_IN); - } - else - cmd->abort_aen = 0; - - instance->aen_cmd = NULL; - megasas_return_cmd(instance, cmd); - - if ((instance->unload == 0) && - ((instance->issuepend_done == 1))) { - struct megasas_aen_event *ev; - ev = kzalloc(sizeof(*ev), GFP_ATOMIC); - if (!ev) { - printk(KERN_ERR "megasas_service_aen: out of memory\n"); - } else { - ev->instance = instance; - instance->ev = ev; - INIT_WORK(&ev->hotplug_work, megasas_aen_polling); - schedule_delayed_work( - (struct delayed_work *)&ev->hotplug_work, 0); - } - } -} - -/* - * Scsi host template for megaraid_sas driver - */ -static struct scsi_host_template megasas_template = { - - .module = THIS_MODULE, - .name = "LSI SAS based MegaRAID driver", - .proc_name = "megaraid_sas", - .slave_configure = megasas_slave_configure, - .slave_alloc = megasas_slave_alloc, - .queuecommand = megasas_queue_command, - .eh_device_reset_handler = megasas_reset_device, - .eh_bus_reset_handler = megasas_reset_bus_host, - .eh_host_reset_handler = megasas_reset_bus_host, - .eh_timed_out = megasas_reset_timer, - .bios_param = megasas_bios_param, - .use_clustering = ENABLE_CLUSTERING, -}; - -/** - * megasas_complete_int_cmd - Completes an internal command - * @instance: Adapter soft state - * @cmd: Command to be completed - * - * The megasas_issue_blocked_cmd() function waits for a command to complete - * after it issues a command. This function wakes up that waiting routine by - * calling wake_up() on the wait queue. - */ -static void -megasas_complete_int_cmd(struct megasas_instance *instance, - struct megasas_cmd *cmd) -{ - cmd->cmd_status = cmd->frame->io.cmd_status; - - if (cmd->cmd_status == ENODATA) { - cmd->cmd_status = 0; - } - wake_up(&instance->int_cmd_wait_q); -} - -/** - * megasas_complete_abort - Completes aborting a command - * @instance: Adapter soft state - * @cmd: Cmd that was issued to abort another cmd - * - * The megasas_issue_blocked_abort_cmd() function waits on abort_cmd_wait_q - * after it issues an abort on a previously issued command. This function - * wakes up all functions waiting on the same wait queue. - */ -static void -megasas_complete_abort(struct megasas_instance *instance, - struct megasas_cmd *cmd) -{ - if (cmd->sync_cmd) { - cmd->sync_cmd = 0; - cmd->cmd_status = 0; - wake_up(&instance->abort_cmd_wait_q); - } - - return; -} - -/** - * megasas_complete_cmd - Completes a command - * @instance: Adapter soft state - * @cmd: Command to be completed - * @alt_status: If non-zero, use this value as status to - * SCSI mid-layer instead of the value returned - * by the FW. This should be used if caller wants - * an alternate status (as in the case of aborted - * commands) - */ -static void -megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, - u8 alt_status) -{ - int exception = 0; - struct megasas_header *hdr = &cmd->frame->hdr; - unsigned long flags; - - /* flag for the retry reset */ - cmd->retry_for_fw_reset = 0; - - if (cmd->scmd) - cmd->scmd->SCp.ptr = NULL; - - switch (hdr->cmd) { - - case MFI_CMD_PD_SCSI_IO: - case MFI_CMD_LD_SCSI_IO: - - /* - * MFI_CMD_PD_SCSI_IO and MFI_CMD_LD_SCSI_IO could have been - * issued either through an IO path or an IOCTL path. If it - * was via IOCTL, we will send it to internal completion. - */ - if (cmd->sync_cmd) { - cmd->sync_cmd = 0; - megasas_complete_int_cmd(instance, cmd); - break; - } - - case MFI_CMD_LD_READ: - case MFI_CMD_LD_WRITE: - - if (alt_status) { - cmd->scmd->result = alt_status << 16; - exception = 1; - } - - if (exception) { - - atomic_dec(&instance->fw_outstanding); - - scsi_dma_unmap(cmd->scmd); - cmd->scmd->scsi_done(cmd->scmd); - megasas_return_cmd(instance, cmd); - - break; - } - - switch (hdr->cmd_status) { - - case MFI_STAT_OK: - cmd->scmd->result = DID_OK << 16; - break; - - case MFI_STAT_SCSI_IO_FAILED: - case MFI_STAT_LD_INIT_IN_PROGRESS: - cmd->scmd->result = - (DID_ERROR << 16) | hdr->scsi_status; - break; - - case MFI_STAT_SCSI_DONE_WITH_ERROR: - - cmd->scmd->result = (DID_OK << 16) | hdr->scsi_status; - - if (hdr->scsi_status == SAM_STAT_CHECK_CONDITION) { - memset(cmd->scmd->sense_buffer, 0, - SCSI_SENSE_BUFFERSIZE); - memcpy(cmd->scmd->sense_buffer, cmd->sense, - hdr->sense_len); - - cmd->scmd->result |= DRIVER_SENSE << 24; - } - - break; - - case MFI_STAT_LD_OFFLINE: - case MFI_STAT_DEVICE_NOT_FOUND: - cmd->scmd->result = DID_BAD_TARGET << 16; - break; - - default: - printk(KERN_DEBUG "megasas: MFI FW status %#x\n", - hdr->cmd_status); - cmd->scmd->result = DID_ERROR << 16; - break; - } - - atomic_dec(&instance->fw_outstanding); - - scsi_dma_unmap(cmd->scmd); - cmd->scmd->scsi_done(cmd->scmd); - megasas_return_cmd(instance, cmd); - - break; - - case MFI_CMD_SMP: - case MFI_CMD_STP: - case MFI_CMD_DCMD: - if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET_INFO || - cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET) { - spin_lock_irqsave(&poll_aen_lock, flags); - megasas_poll_wait_aen = 0; - spin_unlock_irqrestore(&poll_aen_lock, flags); - } - - /* - * See if got an event notification - */ - if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_WAIT) - megasas_service_aen(instance, cmd); - else - megasas_complete_int_cmd(instance, cmd); - - break; - - case MFI_CMD_ABORT: - /* - * Cmd issued to abort another cmd returned - */ - megasas_complete_abort(instance, cmd); - break; - - default: - printk("megasas: Unknown command completed! [0x%X]\n", - hdr->cmd); - break; - } -} - -/** - * megasas_issue_pending_cmds_again - issue all pending cmds - * in FW again because of the fw reset - * @instance: Adapter soft state - */ -static inline void -megasas_issue_pending_cmds_again(struct megasas_instance *instance) -{ - struct megasas_cmd *cmd; - struct list_head clist_local; - union megasas_evt_class_locale class_locale; - unsigned long flags; - u32 seq_num; - - INIT_LIST_HEAD(&clist_local); - spin_lock_irqsave(&instance->hba_lock, flags); - list_splice_init(&instance->internal_reset_pending_q, &clist_local); - spin_unlock_irqrestore(&instance->hba_lock, flags); - - while (!list_empty(&clist_local)) { - cmd = list_entry((&clist_local)->next, - struct megasas_cmd, list); - list_del_init(&cmd->list); - - if (cmd->sync_cmd || cmd->scmd) { - printk(KERN_NOTICE "megaraid_sas: command %p, %p:%d" - "detected to be pending while HBA reset.\n", - cmd, cmd->scmd, cmd->sync_cmd); - - cmd->retry_for_fw_reset++; - - if (cmd->retry_for_fw_reset == 3) { - printk(KERN_NOTICE "megaraid_sas: cmd %p, %p:%d" - "was tried multiple times during reset." - "Shutting down the HBA\n", - cmd, cmd->scmd, cmd->sync_cmd); - megaraid_sas_kill_hba(instance); - - instance->adprecovery = - MEGASAS_HW_CRITICAL_ERROR; - return; - } - } - - if (cmd->sync_cmd == 1) { - if (cmd->scmd) { - printk(KERN_NOTICE "megaraid_sas: unexpected" - "cmd attached to internal command!\n"); - } - printk(KERN_NOTICE "megasas: %p synchronous cmd" - "on the internal reset queue," - "issue it again.\n", cmd); - cmd->cmd_status = ENODATA; - instance->instancet->fire_cmd(instance, - cmd->frame_phys_addr , - 0, instance->reg_set); - } else if (cmd->scmd) { - printk(KERN_NOTICE "megasas: %p scsi cmd [%02x],%#lx" - "detected on the internal queue, issue again.\n", - cmd, cmd->scmd->cmnd[0], cmd->scmd->serial_number); - - atomic_inc(&instance->fw_outstanding); - instance->instancet->fire_cmd(instance, - cmd->frame_phys_addr, - cmd->frame_count-1, instance->reg_set); - } else { - printk(KERN_NOTICE "megasas: %p unexpected cmd on the" - "internal reset defer list while re-issue!!\n", - cmd); - } - } - - if (instance->aen_cmd) { - printk(KERN_NOTICE "megaraid_sas: aen_cmd in def process\n"); - megasas_return_cmd(instance, instance->aen_cmd); - - instance->aen_cmd = NULL; - } - - /* - * Initiate AEN (Asynchronous Event Notification) - */ - seq_num = instance->last_seq_num; - class_locale.members.reserved = 0; - class_locale.members.locale = MR_EVT_LOCALE_ALL; - class_locale.members.class = MR_EVT_CLASS_DEBUG; - - megasas_register_aen(instance, seq_num, class_locale.word); -} - -/** - * Move the internal reset pending commands to a deferred queue. - * - * We move the commands pending at internal reset time to a - * pending queue. This queue would be flushed after successful - * completion of the internal reset sequence. if the internal reset - * did not complete in time, the kernel reset handler would flush - * these commands. - **/ -static void -megasas_internal_reset_defer_cmds(struct megasas_instance *instance) -{ - struct megasas_cmd *cmd; - int i; - u32 max_cmd = instance->max_fw_cmds; - u32 defer_index; - unsigned long flags; - - defer_index = 0; - spin_lock_irqsave(&instance->cmd_pool_lock, flags); - for (i = 0; i < max_cmd; i++) { - cmd = instance->cmd_list[i]; - if (cmd->sync_cmd == 1 || cmd->scmd) { - printk(KERN_NOTICE "megasas: moving cmd[%d]:%p:%d:%p" - "on the defer queue as internal\n", - defer_index, cmd, cmd->sync_cmd, cmd->scmd); - - if (!list_empty(&cmd->list)) { - printk(KERN_NOTICE "megaraid_sas: ERROR while" - " moving this cmd:%p, %d %p, it was" - "discovered on some list?\n", - cmd, cmd->sync_cmd, cmd->scmd); - - list_del_init(&cmd->list); - } - defer_index++; - list_add_tail(&cmd->list, - &instance->internal_reset_pending_q); - } - } - spin_unlock_irqrestore(&instance->cmd_pool_lock, flags); -} - - -static void -process_fw_state_change_wq(struct work_struct *work) -{ - struct megasas_instance *instance = - container_of(work, struct megasas_instance, work_init); - u32 wait; - unsigned long flags; - - if (instance->adprecovery != MEGASAS_ADPRESET_SM_INFAULT) { - printk(KERN_NOTICE "megaraid_sas: error, recovery st %x \n", - instance->adprecovery); - return ; - } - - if (instance->adprecovery == MEGASAS_ADPRESET_SM_INFAULT) { - printk(KERN_NOTICE "megaraid_sas: FW detected to be in fault" - "state, restarting it...\n"); - - instance->instancet->disable_intr(instance->reg_set); - atomic_set(&instance->fw_outstanding, 0); - - atomic_set(&instance->fw_reset_no_pci_access, 1); - instance->instancet->adp_reset(instance, instance->reg_set); - atomic_set(&instance->fw_reset_no_pci_access, 0 ); - - printk(KERN_NOTICE "megaraid_sas: FW restarted successfully," - "initiating next stage...\n"); - - printk(KERN_NOTICE "megaraid_sas: HBA recovery state machine," - "state 2 starting...\n"); - - /*waitting for about 20 second before start the second init*/ - for (wait = 0; wait < 30; wait++) { - msleep(1000); - } - - if (megasas_transition_to_ready(instance)) { - printk(KERN_NOTICE "megaraid_sas:adapter not ready\n"); - - megaraid_sas_kill_hba(instance); - instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR; - return ; - } - - if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1064R) || - (instance->pdev->device == PCI_DEVICE_ID_DELL_PERC5) || - (instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR) - ) { - *instance->consumer = *instance->producer; - } else { - *instance->consumer = 0; - *instance->producer = 0; - } - - megasas_issue_init_mfi(instance); - - spin_lock_irqsave(&instance->hba_lock, flags); - instance->adprecovery = MEGASAS_HBA_OPERATIONAL; - spin_unlock_irqrestore(&instance->hba_lock, flags); - instance->instancet->enable_intr(instance->reg_set); - - megasas_issue_pending_cmds_again(instance); - instance->issuepend_done = 1; - } - return ; -} - -/** - * megasas_deplete_reply_queue - Processes all completed commands - * @instance: Adapter soft state - * @alt_status: Alternate status to be returned to - * SCSI mid-layer instead of the status - * returned by the FW - * Note: this must be called with hba lock held - */ -static int -megasas_deplete_reply_queue(struct megasas_instance *instance, - u8 alt_status) -{ - u32 mfiStatus; - u32 fw_state; - - if ((mfiStatus = instance->instancet->check_reset(instance, - instance->reg_set)) == 1) { - return IRQ_HANDLED; - } - - if ((mfiStatus = instance->instancet->clear_intr( - instance->reg_set) - ) == 0) { - return IRQ_NONE; - } - - instance->mfiStatus = mfiStatus; - - if ((mfiStatus & MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE)) { - fw_state = instance->instancet->read_fw_status_reg( - instance->reg_set) & MFI_STATE_MASK; - - if (fw_state != MFI_STATE_FAULT) { - printk(KERN_NOTICE "megaraid_sas: fw state:%x\n", - fw_state); - } - - if ((fw_state == MFI_STATE_FAULT) && - (instance->disableOnlineCtrlReset == 0)) { - printk(KERN_NOTICE "megaraid_sas: wait adp restart\n"); - - if ((instance->pdev->device == - PCI_DEVICE_ID_LSI_SAS1064R) || - (instance->pdev->device == - PCI_DEVICE_ID_DELL_PERC5) || - (instance->pdev->device == - PCI_DEVICE_ID_LSI_VERDE_ZCR)) { - - *instance->consumer = - MEGASAS_ADPRESET_INPROG_SIGN; - } - - - instance->instancet->disable_intr(instance->reg_set); - instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT; - instance->issuepend_done = 0; - - atomic_set(&instance->fw_outstanding, 0); - megasas_internal_reset_defer_cmds(instance); - - printk(KERN_NOTICE "megasas: fwState=%x, stage:%d\n", - fw_state, instance->adprecovery); - - schedule_work(&instance->work_init); - return IRQ_HANDLED; - - } else { - printk(KERN_NOTICE "megasas: fwstate:%x, dis_OCR=%x\n", - fw_state, instance->disableOnlineCtrlReset); - } - } - - tasklet_schedule(&instance->isr_tasklet); - return IRQ_HANDLED; -} -/** - * megasas_isr - isr entry point - */ -static irqreturn_t megasas_isr(int irq, void *devp) -{ - struct megasas_instance *instance; - unsigned long flags; - irqreturn_t rc; - - if (atomic_read( - &(((struct megasas_instance *)devp)->fw_reset_no_pci_access))) - return IRQ_HANDLED; - - instance = (struct megasas_instance *)devp; - - spin_lock_irqsave(&instance->hba_lock, flags); - rc = megasas_deplete_reply_queue(instance, DID_OK); - spin_unlock_irqrestore(&instance->hba_lock, flags); - - return rc; -} - -/** - * megasas_transition_to_ready - Move the FW to READY state - * @instance: Adapter soft state - * - * During the initialization, FW passes can potentially be in any one of - * several possible states. If the FW in operational, waiting-for-handshake - * states, driver must take steps to bring it to ready state. Otherwise, it - * has to wait for the ready state. - */ -static int -megasas_transition_to_ready(struct megasas_instance* instance) -{ - int i; - u8 max_wait; - u32 fw_state; - u32 cur_state; - u32 abs_state, curr_abs_state; - - fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK; - - if (fw_state != MFI_STATE_READY) - printk(KERN_INFO "megasas: Waiting for FW to come to ready" - " state\n"); - - while (fw_state != MFI_STATE_READY) { - - abs_state = - instance->instancet->read_fw_status_reg(instance->reg_set); - - switch (fw_state) { - - case MFI_STATE_FAULT: - - printk(KERN_DEBUG "megasas: FW in FAULT state!!\n"); - return -ENODEV; - - case MFI_STATE_WAIT_HANDSHAKE: - /* - * Set the CLR bit in inbound doorbell - */ - if ((instance->pdev->device == - PCI_DEVICE_ID_LSI_SAS0073SKINNY) || - (instance->pdev->device == - PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { - - writel( - MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG, - &instance->reg_set->reserved_0[0]); - } else { - writel( - MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG, - &instance->reg_set->inbound_doorbell); - } - - max_wait = MEGASAS_RESET_WAIT_TIME; - cur_state = MFI_STATE_WAIT_HANDSHAKE; - break; - - case MFI_STATE_BOOT_MESSAGE_PENDING: - if ((instance->pdev->device == - PCI_DEVICE_ID_LSI_SAS0073SKINNY) || - (instance->pdev->device == - PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { - writel(MFI_INIT_HOTPLUG, - &instance->reg_set->reserved_0[0]); - } else - writel(MFI_INIT_HOTPLUG, - &instance->reg_set->inbound_doorbell); - - max_wait = MEGASAS_RESET_WAIT_TIME; - cur_state = MFI_STATE_BOOT_MESSAGE_PENDING; - break; - - case MFI_STATE_OPERATIONAL: - /* - * Bring it to READY state; assuming max wait 10 secs - */ - instance->instancet->disable_intr(instance->reg_set); - if ((instance->pdev->device == - PCI_DEVICE_ID_LSI_SAS0073SKINNY) || - (instance->pdev->device == - PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { - writel(MFI_RESET_FLAGS, - &instance->reg_set->reserved_0[0]); - } else - writel(MFI_RESET_FLAGS, - &instance->reg_set->inbound_doorbell); - - max_wait = MEGASAS_RESET_WAIT_TIME; - cur_state = MFI_STATE_OPERATIONAL; - break; - - case MFI_STATE_UNDEFINED: - /* - * This state should not last for more than 2 seconds - */ - max_wait = MEGASAS_RESET_WAIT_TIME; - cur_state = MFI_STATE_UNDEFINED; - break; - - case MFI_STATE_BB_INIT: - max_wait = MEGASAS_RESET_WAIT_TIME; - cur_state = MFI_STATE_BB_INIT; - break; - - case MFI_STATE_FW_INIT: - max_wait = MEGASAS_RESET_WAIT_TIME; - cur_state = MFI_STATE_FW_INIT; - break; - - case MFI_STATE_FW_INIT_2: - max_wait = MEGASAS_RESET_WAIT_TIME; - cur_state = MFI_STATE_FW_INIT_2; - break; - - case MFI_STATE_DEVICE_SCAN: - max_wait = MEGASAS_RESET_WAIT_TIME; - cur_state = MFI_STATE_DEVICE_SCAN; - break; - - case MFI_STATE_FLUSH_CACHE: - max_wait = MEGASAS_RESET_WAIT_TIME; - cur_state = MFI_STATE_FLUSH_CACHE; - break; - - default: - printk(KERN_DEBUG "megasas: Unknown state 0x%x\n", - fw_state); - return -ENODEV; - } - - /* - * The cur_state should not last for more than max_wait secs - */ - for (i = 0; i < (max_wait * 1000); i++) { - fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & - MFI_STATE_MASK ; - curr_abs_state = - instance->instancet->read_fw_status_reg(instance->reg_set); - - if (abs_state == curr_abs_state) { - msleep(1); - } else - break; - } - - /* - * Return error if fw_state hasn't changed after max_wait - */ - if (curr_abs_state == abs_state) { - printk(KERN_DEBUG "FW state [%d] hasn't changed " - "in %d secs\n", fw_state, max_wait); - return -ENODEV; - } - } - printk(KERN_INFO "megasas: FW now in Ready state\n"); - - return 0; -} - -/** - * megasas_teardown_frame_pool - Destroy the cmd frame DMA pool - * @instance: Adapter soft state - */ -static void megasas_teardown_frame_pool(struct megasas_instance *instance) -{ - int i; - u32 max_cmd = instance->max_fw_cmds; - struct megasas_cmd *cmd; - - if (!instance->frame_dma_pool) - return; - - /* - * Return all frames to pool - */ - for (i = 0; i < max_cmd; i++) { - - cmd = instance->cmd_list[i]; - - if (cmd->frame) - pci_pool_free(instance->frame_dma_pool, cmd->frame, - cmd->frame_phys_addr); - - if (cmd->sense) - pci_pool_free(instance->sense_dma_pool, cmd->sense, - cmd->sense_phys_addr); - } - - /* - * Now destroy the pool itself - */ - pci_pool_destroy(instance->frame_dma_pool); - pci_pool_destroy(instance->sense_dma_pool); - - instance->frame_dma_pool = NULL; - instance->sense_dma_pool = NULL; -} - -/** - * megasas_create_frame_pool - Creates DMA pool for cmd frames - * @instance: Adapter soft state - * - * Each command packet has an embedded DMA memory buffer that is used for - * filling MFI frame and the SG list that immediately follows the frame. This - * function creates those DMA memory buffers for each command packet by using - * PCI pool facility. - */ -static int megasas_create_frame_pool(struct megasas_instance *instance) -{ - int i; - u32 max_cmd; - u32 sge_sz; - u32 sgl_sz; - u32 total_sz; - u32 frame_count; - struct megasas_cmd *cmd; - - max_cmd = instance->max_fw_cmds; - - /* - * Size of our frame is 64 bytes for MFI frame, followed by max SG - * elements and finally SCSI_SENSE_BUFFERSIZE bytes for sense buffer - */ - sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : - sizeof(struct megasas_sge32); - - if (instance->flag_ieee) { - sge_sz = sizeof(struct megasas_sge_skinny); - } - - /* - * Calculated the number of 64byte frames required for SGL - */ - sgl_sz = sge_sz * instance->max_num_sge; - frame_count = (sgl_sz + MEGAMFI_FRAME_SIZE - 1) / MEGAMFI_FRAME_SIZE; - frame_count = 15; - - /* - * We need one extra frame for the MFI command - */ - frame_count++; - - total_sz = MEGAMFI_FRAME_SIZE * frame_count; - /* - * Use DMA pool facility provided by PCI layer - */ - instance->frame_dma_pool = pci_pool_create("megasas frame pool", - instance->pdev, total_sz, 64, - 0); - - if (!instance->frame_dma_pool) { - printk(KERN_DEBUG "megasas: failed to setup frame pool\n"); - return -ENOMEM; - } - - instance->sense_dma_pool = pci_pool_create("megasas sense pool", - instance->pdev, 128, 4, 0); - - if (!instance->sense_dma_pool) { - printk(KERN_DEBUG "megasas: failed to setup sense pool\n"); - - pci_pool_destroy(instance->frame_dma_pool); - instance->frame_dma_pool = NULL; - - return -ENOMEM; - } - - /* - * Allocate and attach a frame to each of the commands in cmd_list. - * By making cmd->index as the context instead of the &cmd, we can - * always use 32bit context regardless of the architecture - */ - for (i = 0; i < max_cmd; i++) { - - cmd = instance->cmd_list[i]; - - cmd->frame = pci_pool_alloc(instance->frame_dma_pool, - GFP_KERNEL, &cmd->frame_phys_addr); - - cmd->sense = pci_pool_alloc(instance->sense_dma_pool, - GFP_KERNEL, &cmd->sense_phys_addr); - - /* - * megasas_teardown_frame_pool() takes care of freeing - * whatever has been allocated - */ - if (!cmd->frame || !cmd->sense) { - printk(KERN_DEBUG "megasas: pci_pool_alloc failed \n"); - megasas_teardown_frame_pool(instance); - return -ENOMEM; - } - - memset(cmd->frame, 0, total_sz); - cmd->frame->io.context = cmd->index; - cmd->frame->io.pad_0 = 0; - } - - return 0; -} - -/** - * megasas_free_cmds - Free all the cmds in the free cmd pool - * @instance: Adapter soft state - */ -static void megasas_free_cmds(struct megasas_instance *instance) -{ - int i; - /* First free the MFI frame pool */ - megasas_teardown_frame_pool(instance); - - /* Free all the commands in the cmd_list */ - for (i = 0; i < instance->max_fw_cmds; i++) - kfree(instance->cmd_list[i]); - - /* Free the cmd_list buffer itself */ - kfree(instance->cmd_list); - instance->cmd_list = NULL; - - INIT_LIST_HEAD(&instance->cmd_pool); -} - -/** - * megasas_alloc_cmds - Allocates the command packets - * @instance: Adapter soft state - * - * Each command that is issued to the FW, whether IO commands from the OS or - * internal commands like IOCTLs, are wrapped in local data structure called - * megasas_cmd. The frame embedded in this megasas_cmd is actually issued to - * the FW. - * - * Each frame has a 32-bit field called context (tag). This context is used - * to get back the megasas_cmd from the frame when a frame gets completed in - * the ISR. Typically the address of the megasas_cmd itself would be used as - * the context. But we wanted to keep the differences between 32 and 64 bit - * systems to the mininum. We always use 32 bit integers for the context. In - * this driver, the 32 bit values are the indices into an array cmd_list. - * This array is used only to look up the megasas_cmd given the context. The - * free commands themselves are maintained in a linked list called cmd_pool. - */ -static int megasas_alloc_cmds(struct megasas_instance *instance) -{ - int i; - int j; - u32 max_cmd; - struct megasas_cmd *cmd; - - max_cmd = instance->max_fw_cmds; - - /* - * instance->cmd_list is an array of struct megasas_cmd pointers. - * Allocate the dynamic array first and then allocate individual - * commands. - */ - instance->cmd_list = kcalloc(max_cmd, sizeof(struct megasas_cmd*), GFP_KERNEL); - - if (!instance->cmd_list) { - printk(KERN_DEBUG "megasas: out of memory\n"); - return -ENOMEM; - } - - - for (i = 0; i < max_cmd; i++) { - instance->cmd_list[i] = kmalloc(sizeof(struct megasas_cmd), - GFP_KERNEL); - - if (!instance->cmd_list[i]) { - - for (j = 0; j < i; j++) - kfree(instance->cmd_list[j]); - - kfree(instance->cmd_list); - instance->cmd_list = NULL; - - return -ENOMEM; - } - } - - /* - * Add all the commands to command pool (instance->cmd_pool) - */ - for (i = 0; i < max_cmd; i++) { - cmd = instance->cmd_list[i]; - memset(cmd, 0, sizeof(struct megasas_cmd)); - cmd->index = i; - cmd->scmd = NULL; - cmd->instance = instance; - - list_add_tail(&cmd->list, &instance->cmd_pool); - } - - /* - * Create a frame pool and assign one frame to each cmd - */ - if (megasas_create_frame_pool(instance)) { - printk(KERN_DEBUG "megasas: Error creating frame DMA pool\n"); - megasas_free_cmds(instance); - } - - return 0; -} - -/* - * megasas_get_pd_list_info - Returns FW's pd_list structure - * @instance: Adapter soft state - * @pd_list: pd_list structure - * - * Issues an internal command (DCMD) to get the FW's controller PD - * list structure. This information is mainly used to find out SYSTEM - * supported by the FW. - */ -static int -megasas_get_pd_list(struct megasas_instance *instance) -{ - int ret = 0, pd_index = 0; - struct megasas_cmd *cmd; - struct megasas_dcmd_frame *dcmd; - struct MR_PD_LIST *ci; - struct MR_PD_ADDRESS *pd_addr; - dma_addr_t ci_h = 0; - - cmd = megasas_get_cmd(instance); - - if (!cmd) { - printk(KERN_DEBUG "megasas (get_pd_list): Failed to get cmd\n"); - return -ENOMEM; - } - - dcmd = &cmd->frame->dcmd; - - ci = pci_alloc_consistent(instance->pdev, - MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), &ci_h); - - if (!ci) { - printk(KERN_DEBUG "Failed to alloc mem for pd_list\n"); - megasas_return_cmd(instance, cmd); - return -ENOMEM; - } - - memset(ci, 0, sizeof(*ci)); - memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); - - dcmd->mbox.b[0] = MR_PD_QUERY_TYPE_EXPOSED_TO_HOST; - dcmd->mbox.b[1] = 0; - dcmd->cmd = MFI_CMD_DCMD; - dcmd->cmd_status = 0xFF; - dcmd->sge_count = 1; - dcmd->flags = MFI_FRAME_DIR_READ; - dcmd->timeout = 0; - dcmd->pad_0 = 0; - dcmd->data_xfer_len = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST); - dcmd->opcode = MR_DCMD_PD_LIST_QUERY; - dcmd->sgl.sge32[0].phys_addr = ci_h; - dcmd->sgl.sge32[0].length = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST); - - if (!megasas_issue_polled(instance, cmd)) { - ret = 0; - } else { - ret = -1; - } - - /* - * the following function will get the instance PD LIST. - */ - - pd_addr = ci->addr; - - if ( ret == 0 && - (ci->count < - (MEGASAS_MAX_PD_CHANNELS * MEGASAS_MAX_DEV_PER_CHANNEL))) { - - memset(instance->pd_list, 0, - MEGASAS_MAX_PD * sizeof(struct megasas_pd_list)); - - for (pd_index = 0; pd_index < ci->count; pd_index++) { - - instance->pd_list[pd_addr->deviceId].tid = - pd_addr->deviceId; - instance->pd_list[pd_addr->deviceId].driveType = - pd_addr->scsiDevType; - instance->pd_list[pd_addr->deviceId].driveState = - MR_PD_STATE_SYSTEM; - pd_addr++; - } - } - - pci_free_consistent(instance->pdev, - MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), - ci, ci_h); - megasas_return_cmd(instance, cmd); - - return ret; -} - -/* - * megasas_get_ld_list_info - Returns FW's ld_list structure - * @instance: Adapter soft state - * @ld_list: ld_list structure - * - * Issues an internal command (DCMD) to get the FW's controller PD - * list structure. This information is mainly used to find out SYSTEM - * supported by the FW. - */ -static int -megasas_get_ld_list(struct megasas_instance *instance) -{ - int ret = 0, ld_index = 0, ids = 0; - struct megasas_cmd *cmd; - struct megasas_dcmd_frame *dcmd; - struct MR_LD_LIST *ci; - dma_addr_t ci_h = 0; - - cmd = megasas_get_cmd(instance); - - if (!cmd) { - printk(KERN_DEBUG "megasas_get_ld_list: Failed to get cmd\n"); - return -ENOMEM; - } - - dcmd = &cmd->frame->dcmd; - - ci = pci_alloc_consistent(instance->pdev, - sizeof(struct MR_LD_LIST), - &ci_h); - - if (!ci) { - printk(KERN_DEBUG "Failed to alloc mem in get_ld_list\n"); - megasas_return_cmd(instance, cmd); - return -ENOMEM; - } - - memset(ci, 0, sizeof(*ci)); - memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); - - dcmd->cmd = MFI_CMD_DCMD; - dcmd->cmd_status = 0xFF; - dcmd->sge_count = 1; - dcmd->flags = MFI_FRAME_DIR_READ; - dcmd->timeout = 0; - dcmd->data_xfer_len = sizeof(struct MR_LD_LIST); - dcmd->opcode = MR_DCMD_LD_GET_LIST; - dcmd->sgl.sge32[0].phys_addr = ci_h; - dcmd->sgl.sge32[0].length = sizeof(struct MR_LD_LIST); - dcmd->pad_0 = 0; - - if (!megasas_issue_polled(instance, cmd)) { - ret = 0; - } else { - ret = -1; - } - - /* the following function will get the instance PD LIST */ - - if ((ret == 0) && (ci->ldCount <= MAX_LOGICAL_DRIVES)) { - memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS); - - for (ld_index = 0; ld_index < ci->ldCount; ld_index++) { - if (ci->ldList[ld_index].state != 0) { - ids = ci->ldList[ld_index].ref.targetId; - instance->ld_ids[ids] = - ci->ldList[ld_index].ref.targetId; - } - } - } - - pci_free_consistent(instance->pdev, - sizeof(struct MR_LD_LIST), - ci, - ci_h); - - megasas_return_cmd(instance, cmd); - return ret; -} - -/** - * megasas_get_controller_info - Returns FW's controller structure - * @instance: Adapter soft state - * @ctrl_info: Controller information structure - * - * Issues an internal command (DCMD) to get the FW's controller structure. - * This information is mainly used to find out the maximum IO transfer per - * command supported by the FW. - */ -static int -megasas_get_ctrl_info(struct megasas_instance *instance, - struct megasas_ctrl_info *ctrl_info) -{ - int ret = 0; - struct megasas_cmd *cmd; - struct megasas_dcmd_frame *dcmd; - struct megasas_ctrl_info *ci; - dma_addr_t ci_h = 0; - - cmd = megasas_get_cmd(instance); - - if (!cmd) { - printk(KERN_DEBUG "megasas: Failed to get a free cmd\n"); - return -ENOMEM; - } - - dcmd = &cmd->frame->dcmd; - - ci = pci_alloc_consistent(instance->pdev, - sizeof(struct megasas_ctrl_info), &ci_h); - - if (!ci) { - printk(KERN_DEBUG "Failed to alloc mem for ctrl info\n"); - megasas_return_cmd(instance, cmd); - return -ENOMEM; - } - - memset(ci, 0, sizeof(*ci)); - memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); - - dcmd->cmd = MFI_CMD_DCMD; - dcmd->cmd_status = 0xFF; - dcmd->sge_count = 1; - dcmd->flags = MFI_FRAME_DIR_READ; - dcmd->timeout = 0; - dcmd->pad_0 = 0; - dcmd->data_xfer_len = sizeof(struct megasas_ctrl_info); - dcmd->opcode = MR_DCMD_CTRL_GET_INFO; - dcmd->sgl.sge32[0].phys_addr = ci_h; - dcmd->sgl.sge32[0].length = sizeof(struct megasas_ctrl_info); - - if (!megasas_issue_polled(instance, cmd)) { - ret = 0; - memcpy(ctrl_info, ci, sizeof(struct megasas_ctrl_info)); - } else { - ret = -1; - } - - pci_free_consistent(instance->pdev, sizeof(struct megasas_ctrl_info), - ci, ci_h); - - megasas_return_cmd(instance, cmd); - return ret; -} - -/** - * megasas_issue_init_mfi - Initializes the FW - * @instance: Adapter soft state - * - * Issues the INIT MFI cmd - */ -static int -megasas_issue_init_mfi(struct megasas_instance *instance) -{ - u32 context; - - struct megasas_cmd *cmd; - - struct megasas_init_frame *init_frame; - struct megasas_init_queue_info *initq_info; - dma_addr_t init_frame_h; - dma_addr_t initq_info_h; - - /* - * Prepare a init frame. Note the init frame points to queue info - * structure. Each frame has SGL allocated after first 64 bytes. For - * this frame - since we don't need any SGL - we use SGL's space as - * queue info structure - * - * We will not get a NULL command below. We just created the pool. - */ - cmd = megasas_get_cmd(instance); - - init_frame = (struct megasas_init_frame *)cmd->frame; - initq_info = (struct megasas_init_queue_info *) - ((unsigned long)init_frame + 64); - - init_frame_h = cmd->frame_phys_addr; - initq_info_h = init_frame_h + 64; - - context = init_frame->context; - memset(init_frame, 0, MEGAMFI_FRAME_SIZE); - memset(initq_info, 0, sizeof(struct megasas_init_queue_info)); - init_frame->context = context; - - initq_info->reply_queue_entries = instance->max_fw_cmds + 1; - initq_info->reply_queue_start_phys_addr_lo = instance->reply_queue_h; - - initq_info->producer_index_phys_addr_lo = instance->producer_h; - initq_info->consumer_index_phys_addr_lo = instance->consumer_h; - - init_frame->cmd = MFI_CMD_INIT; - init_frame->cmd_status = 0xFF; - init_frame->queue_info_new_phys_addr_lo = initq_info_h; - - init_frame->data_xfer_len = sizeof(struct megasas_init_queue_info); - - /* - * disable the intr before firing the init frame to FW - */ - instance->instancet->disable_intr(instance->reg_set); - - /* - * Issue the init frame in polled mode - */ - - if (megasas_issue_polled(instance, cmd)) { - printk(KERN_ERR "megasas: Failed to init firmware\n"); - megasas_return_cmd(instance, cmd); - goto fail_fw_init; - } - - megasas_return_cmd(instance, cmd); - - return 0; - -fail_fw_init: - return -EINVAL; -} - -/** - * megasas_start_timer - Initializes a timer object - * @instance: Adapter soft state - * @timer: timer object to be initialized - * @fn: timer function - * @interval: time interval between timer function call - */ -static inline void -megasas_start_timer(struct megasas_instance *instance, - struct timer_list *timer, - void *fn, unsigned long interval) -{ - init_timer(timer); - timer->expires = jiffies + interval; - timer->data = (unsigned long)instance; - timer->function = fn; - add_timer(timer); -} - -/** - * megasas_io_completion_timer - Timer fn - * @instance_addr: Address of adapter soft state - * - * Schedules tasklet for cmd completion - * if poll_mode_io is set - */ -static void -megasas_io_completion_timer(unsigned long instance_addr) -{ - struct megasas_instance *instance = - (struct megasas_instance *)instance_addr; - - if (atomic_read(&instance->fw_outstanding)) - tasklet_schedule(&instance->isr_tasklet); - - /* Restart timer */ - if (poll_mode_io) - mod_timer(&instance->io_completion_timer, - jiffies + MEGASAS_COMPLETION_TIMER_INTERVAL); -} - -/** - * megasas_init_mfi - Initializes the FW - * @instance: Adapter soft state - * - * This is the main function for initializing MFI firmware. - */ -static int megasas_init_mfi(struct megasas_instance *instance) -{ - u32 context_sz; - u32 reply_q_sz; - u32 max_sectors_1; - u32 max_sectors_2; - u32 tmp_sectors; - struct megasas_register_set __iomem *reg_set; - struct megasas_ctrl_info *ctrl_info; - /* - * Map the message registers - */ - if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078GEN2) || - (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) || - (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || - (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0079GEN2)) { - instance->base_addr = pci_resource_start(instance->pdev, 1); - } else { - instance->base_addr = pci_resource_start(instance->pdev, 0); - } - - if (pci_request_selected_regions(instance->pdev, - pci_select_bars(instance->pdev, IORESOURCE_MEM), - "megasas: LSI")) { - printk(KERN_DEBUG "megasas: IO memory region busy!\n"); - return -EBUSY; - } - - instance->reg_set = ioremap_nocache(instance->base_addr, 8192); - - if (!instance->reg_set) { - printk(KERN_DEBUG "megasas: Failed to map IO mem\n"); - goto fail_ioremap; - } - - reg_set = instance->reg_set; - - switch(instance->pdev->device) - { - case PCI_DEVICE_ID_LSI_SAS1078R: - case PCI_DEVICE_ID_LSI_SAS1078DE: - instance->instancet = &megasas_instance_template_ppc; - break; - case PCI_DEVICE_ID_LSI_SAS1078GEN2: - case PCI_DEVICE_ID_LSI_SAS0079GEN2: - instance->instancet = &megasas_instance_template_gen2; - break; - case PCI_DEVICE_ID_LSI_SAS0073SKINNY: - case PCI_DEVICE_ID_LSI_SAS0071SKINNY: - instance->instancet = &megasas_instance_template_skinny; - break; - case PCI_DEVICE_ID_LSI_SAS1064R: - case PCI_DEVICE_ID_DELL_PERC5: - default: - instance->instancet = &megasas_instance_template_xscale; - break; - } - - /* - * We expect the FW state to be READY - */ - if (megasas_transition_to_ready(instance)) - goto fail_ready_state; - - /* - * Get various operational parameters from status register - */ - instance->max_fw_cmds = instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF; - /* - * Reduce the max supported cmds by 1. This is to ensure that the - * reply_q_sz (1 more than the max cmd that driver may send) - * does not exceed max cmds that the FW can support - */ - instance->max_fw_cmds = instance->max_fw_cmds-1; - instance->max_num_sge = (instance->instancet->read_fw_status_reg(reg_set) & 0xFF0000) >> - 0x10; - /* - * Create a pool of commands - */ - if (megasas_alloc_cmds(instance)) - goto fail_alloc_cmds; - - /* - * Allocate memory for reply queue. Length of reply queue should - * be _one_ more than the maximum commands handled by the firmware. - * - * Note: When FW completes commands, it places corresponding contex - * values in this circular reply queue. This circular queue is a fairly - * typical producer-consumer queue. FW is the producer (of completed - * commands) and the driver is the consumer. - */ - context_sz = sizeof(u32); - reply_q_sz = context_sz * (instance->max_fw_cmds + 1); - - instance->reply_queue = pci_alloc_consistent(instance->pdev, - reply_q_sz, - &instance->reply_queue_h); - - if (!instance->reply_queue) { - printk(KERN_DEBUG "megasas: Out of DMA mem for reply queue\n"); - goto fail_reply_queue; - } - - if (megasas_issue_init_mfi(instance)) - goto fail_fw_init; - - instance->fw_support_ieee = 0; - instance->fw_support_ieee = - (instance->instancet->read_fw_status_reg(reg_set) & - 0x04000000); - - printk(KERN_NOTICE "megasas_init_mfi: fw_support_ieee=%d", - instance->fw_support_ieee); - - if (instance->fw_support_ieee) - instance->flag_ieee = 1; - - /** for passthrough - * the following function will get the PD LIST. - */ - - memset(instance->pd_list, 0 , - (MEGASAS_MAX_PD * sizeof(struct megasas_pd_list))); - megasas_get_pd_list(instance); - - memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS); - megasas_get_ld_list(instance); - - ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL); - - /* - * Compute the max allowed sectors per IO: The controller info has two - * limits on max sectors. Driver should use the minimum of these two. - * - * 1 << stripe_sz_ops.min = max sectors per strip - * - * Note that older firmwares ( < FW ver 30) didn't report information - * to calculate max_sectors_1. So the number ended up as zero always. - */ - tmp_sectors = 0; - if (ctrl_info && !megasas_get_ctrl_info(instance, ctrl_info)) { - - max_sectors_1 = (1 << ctrl_info->stripe_sz_ops.min) * - ctrl_info->max_strips_per_io; - max_sectors_2 = ctrl_info->max_request_size; - - tmp_sectors = min_t(u32, max_sectors_1 , max_sectors_2); - instance->disableOnlineCtrlReset = - ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset; - } - - instance->max_sectors_per_req = instance->max_num_sge * - PAGE_SIZE / 512; - if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors)) - instance->max_sectors_per_req = tmp_sectors; - - kfree(ctrl_info); - - /* - * Setup tasklet for cmd completion - */ - - tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc, - (unsigned long)instance); - - /* Initialize the cmd completion timer */ - if (poll_mode_io) - megasas_start_timer(instance, &instance->io_completion_timer, - megasas_io_completion_timer, - MEGASAS_COMPLETION_TIMER_INTERVAL); - return 0; - - fail_fw_init: - - pci_free_consistent(instance->pdev, reply_q_sz, - instance->reply_queue, instance->reply_queue_h); - fail_reply_queue: - megasas_free_cmds(instance); - - fail_alloc_cmds: - fail_ready_state: - iounmap(instance->reg_set); - - fail_ioremap: - pci_release_selected_regions(instance->pdev, - pci_select_bars(instance->pdev, IORESOURCE_MEM)); - - return -EINVAL; -} - -/** - * megasas_release_mfi - Reverses the FW initialization - * @intance: Adapter soft state - */ -static void megasas_release_mfi(struct megasas_instance *instance) -{ - u32 reply_q_sz = sizeof(u32) * (instance->max_fw_cmds + 1); - - pci_free_consistent(instance->pdev, reply_q_sz, - instance->reply_queue, instance->reply_queue_h); - - megasas_free_cmds(instance); - - iounmap(instance->reg_set); - - pci_release_selected_regions(instance->pdev, - pci_select_bars(instance->pdev, IORESOURCE_MEM)); -} - -/** - * megasas_get_seq_num - Gets latest event sequence numbers - * @instance: Adapter soft state - * @eli: FW event log sequence numbers information - * - * FW maintains a log of all events in a non-volatile area. Upper layers would - * usually find out the latest sequence number of the events, the seq number at - * the boot etc. They would "read" all the events below the latest seq number - * by issuing a direct fw cmd (DCMD). For the future events (beyond latest seq - * number), they would subsribe to AEN (asynchronous event notification) and - * wait for the events to happen. - */ -static int -megasas_get_seq_num(struct megasas_instance *instance, - struct megasas_evt_log_info *eli) -{ - struct megasas_cmd *cmd; - struct megasas_dcmd_frame *dcmd; - struct megasas_evt_log_info *el_info; - dma_addr_t el_info_h = 0; - - cmd = megasas_get_cmd(instance); - - if (!cmd) { - return -ENOMEM; - } - - dcmd = &cmd->frame->dcmd; - el_info = pci_alloc_consistent(instance->pdev, - sizeof(struct megasas_evt_log_info), - &el_info_h); - - if (!el_info) { - megasas_return_cmd(instance, cmd); - return -ENOMEM; - } - - memset(el_info, 0, sizeof(*el_info)); - memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); - - dcmd->cmd = MFI_CMD_DCMD; - dcmd->cmd_status = 0x0; - dcmd->sge_count = 1; - dcmd->flags = MFI_FRAME_DIR_READ; - dcmd->timeout = 0; - dcmd->pad_0 = 0; - dcmd->data_xfer_len = sizeof(struct megasas_evt_log_info); - dcmd->opcode = MR_DCMD_CTRL_EVENT_GET_INFO; - dcmd->sgl.sge32[0].phys_addr = el_info_h; - dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_log_info); - - megasas_issue_blocked_cmd(instance, cmd); - - /* - * Copy the data back into callers buffer - */ - memcpy(eli, el_info, sizeof(struct megasas_evt_log_info)); - - pci_free_consistent(instance->pdev, sizeof(struct megasas_evt_log_info), - el_info, el_info_h); - - megasas_return_cmd(instance, cmd); - - return 0; -} - -/** - * megasas_register_aen - Registers for asynchronous event notification - * @instance: Adapter soft state - * @seq_num: The starting sequence number - * @class_locale: Class of the event - * - * This function subscribes for AEN for events beyond the @seq_num. It requests - * to be notified if and only if the event is of type @class_locale - */ -static int -megasas_register_aen(struct megasas_instance *instance, u32 seq_num, - u32 class_locale_word) -{ - int ret_val; - struct megasas_cmd *cmd; - struct megasas_dcmd_frame *dcmd; - union megasas_evt_class_locale curr_aen; - union megasas_evt_class_locale prev_aen; - - /* - * If there an AEN pending already (aen_cmd), check if the - * class_locale of that pending AEN is inclusive of the new - * AEN request we currently have. If it is, then we don't have - * to do anything. In other words, whichever events the current - * AEN request is subscribing to, have already been subscribed - * to. - * - * If the old_cmd is _not_ inclusive, then we have to abort - * that command, form a class_locale that is superset of both - * old and current and re-issue to the FW - */ - - curr_aen.word = class_locale_word; - - if (instance->aen_cmd) { - - prev_aen.word = instance->aen_cmd->frame->dcmd.mbox.w[1]; - - /* - * A class whose enum value is smaller is inclusive of all - * higher values. If a PROGRESS (= -1) was previously - * registered, then a new registration requests for higher - * classes need not be sent to FW. They are automatically - * included. - * - * Locale numbers don't have such hierarchy. They are bitmap - * values - */ - if ((prev_aen.members.class <= curr_aen.members.class) && - !((prev_aen.members.locale & curr_aen.members.locale) ^ - curr_aen.members.locale)) { - /* - * Previously issued event registration includes - * current request. Nothing to do. - */ - return 0; - } else { - curr_aen.members.locale |= prev_aen.members.locale; - - if (prev_aen.members.class < curr_aen.members.class) - curr_aen.members.class = prev_aen.members.class; - - instance->aen_cmd->abort_aen = 1; - ret_val = megasas_issue_blocked_abort_cmd(instance, - instance-> - aen_cmd); - - if (ret_val) { - printk(KERN_DEBUG "megasas: Failed to abort " - "previous AEN command\n"); - return ret_val; - } - } - } - - cmd = megasas_get_cmd(instance); - - if (!cmd) - return -ENOMEM; - - dcmd = &cmd->frame->dcmd; - - memset(instance->evt_detail, 0, sizeof(struct megasas_evt_detail)); - - /* - * Prepare DCMD for aen registration - */ - memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); - - dcmd->cmd = MFI_CMD_DCMD; - dcmd->cmd_status = 0x0; - dcmd->sge_count = 1; - dcmd->flags = MFI_FRAME_DIR_READ; - dcmd->timeout = 0; - dcmd->pad_0 = 0; - instance->last_seq_num = seq_num; - dcmd->data_xfer_len = sizeof(struct megasas_evt_detail); - dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT; - dcmd->mbox.w[0] = seq_num; - dcmd->mbox.w[1] = curr_aen.word; - dcmd->sgl.sge32[0].phys_addr = (u32) instance->evt_detail_h; - dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_detail); - - if (instance->aen_cmd != NULL) { - megasas_return_cmd(instance, cmd); - return 0; - } - - /* - * Store reference to the cmd used to register for AEN. When an - * application wants us to register for AEN, we have to abort this - * cmd and re-register with a new EVENT LOCALE supplied by that app - */ - instance->aen_cmd = cmd; - - /* - * Issue the aen registration frame - */ - instance->instancet->fire_cmd(instance, - cmd->frame_phys_addr, 0, instance->reg_set); - - return 0; -} - -/** - * megasas_start_aen - Subscribes to AEN during driver load time - * @instance: Adapter soft state - */ -static int megasas_start_aen(struct megasas_instance *instance) -{ - struct megasas_evt_log_info eli; - union megasas_evt_class_locale class_locale; - - /* - * Get the latest sequence number from FW - */ - memset(&eli, 0, sizeof(eli)); - - if (megasas_get_seq_num(instance, &eli)) - return -1; - - /* - * Register AEN with FW for latest sequence number plus 1 - */ - class_locale.members.reserved = 0; - class_locale.members.locale = MR_EVT_LOCALE_ALL; - class_locale.members.class = MR_EVT_CLASS_DEBUG; - - return megasas_register_aen(instance, eli.newest_seq_num + 1, - class_locale.word); -} - -/** - * megasas_io_attach - Attaches this driver to SCSI mid-layer - * @instance: Adapter soft state - */ -static int megasas_io_attach(struct megasas_instance *instance) -{ - struct Scsi_Host *host = instance->host; - - /* - * Export parameters required by SCSI mid-layer - */ - host->irq = instance->pdev->irq; - host->unique_id = instance->unique_id; - if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || - (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { - host->can_queue = - instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS; - } else - host->can_queue = - instance->max_fw_cmds - MEGASAS_INT_CMDS; - host->this_id = instance->init_id; - host->sg_tablesize = instance->max_num_sge; - /* - * Check if the module parameter value for max_sectors can be used - */ - if (max_sectors && max_sectors < instance->max_sectors_per_req) - instance->max_sectors_per_req = max_sectors; - else { - if (max_sectors) { - if (((instance->pdev->device == - PCI_DEVICE_ID_LSI_SAS1078GEN2) || - (instance->pdev->device == - PCI_DEVICE_ID_LSI_SAS0079GEN2)) && - (max_sectors <= MEGASAS_MAX_SECTORS)) { - instance->max_sectors_per_req = max_sectors; - } else { - printk(KERN_INFO "megasas: max_sectors should be > 0" - "and <= %d (or < 1MB for GEN2 controller)\n", - instance->max_sectors_per_req); - } - } - } - - host->max_sectors = instance->max_sectors_per_req; - host->cmd_per_lun = 128; - host->max_channel = MEGASAS_MAX_CHANNELS - 1; - host->max_id = MEGASAS_MAX_DEV_PER_CHANNEL; - host->max_lun = MEGASAS_MAX_LUN; - host->max_cmd_len = 16; - - /* - * Notify the mid-layer about the new controller - */ - if (scsi_add_host(host, &instance->pdev->dev)) { - printk(KERN_DEBUG "megasas: scsi_add_host failed\n"); - return -ENODEV; - } - - /* - * Trigger SCSI to scan our drives - */ - scsi_scan_host(host); - return 0; -} - -static int -megasas_set_dma_mask(struct pci_dev *pdev) -{ - /* - * All our contollers are capable of performing 64-bit DMA - */ - if (IS_DMA64) { - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) { - - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) - goto fail_set_dma_mask; - } - } else { - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) - goto fail_set_dma_mask; - } - return 0; - -fail_set_dma_mask: - return 1; -} - -/** - * megasas_probe_one - PCI hotplug entry point - * @pdev: PCI device structure - * @id: PCI ids of supported hotplugged adapter - */ -static int __devinit -megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) -{ - int rval; - struct Scsi_Host *host; - struct megasas_instance *instance; - - /* - * Announce PCI information - */ - printk(KERN_INFO "megasas: %#4.04x:%#4.04x:%#4.04x:%#4.04x: ", - pdev->vendor, pdev->device, pdev->subsystem_vendor, - pdev->subsystem_device); - - printk("bus %d:slot %d:func %d\n", - pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); - - /* - * PCI prepping: enable device set bus mastering and dma mask - */ - rval = pci_enable_device_mem(pdev); - - if (rval) { - return rval; - } - - pci_set_master(pdev); - - if (megasas_set_dma_mask(pdev)) - goto fail_set_dma_mask; - - host = scsi_host_alloc(&megasas_template, - sizeof(struct megasas_instance)); - - if (!host) { - printk(KERN_DEBUG "megasas: scsi_host_alloc failed\n"); - goto fail_alloc_instance; - } - - instance = (struct megasas_instance *)host->hostdata; - memset(instance, 0, sizeof(*instance)); - atomic_set( &instance->fw_reset_no_pci_access, 0 ); - - instance->producer = pci_alloc_consistent(pdev, sizeof(u32), - &instance->producer_h); - instance->consumer = pci_alloc_consistent(pdev, sizeof(u32), - &instance->consumer_h); - - if (!instance->producer || !instance->consumer) { - printk(KERN_DEBUG "megasas: Failed to allocate memory for " - "producer, consumer\n"); - goto fail_alloc_dma_buf; - } - - *instance->producer = 0; - *instance->consumer = 0; - megasas_poll_wait_aen = 0; - instance->flag_ieee = 0; - instance->ev = NULL; - instance->issuepend_done = 1; - instance->adprecovery = MEGASAS_HBA_OPERATIONAL; - megasas_poll_wait_aen = 0; - - instance->evt_detail = pci_alloc_consistent(pdev, - sizeof(struct - megasas_evt_detail), - &instance->evt_detail_h); - - if (!instance->evt_detail) { - printk(KERN_DEBUG "megasas: Failed to allocate memory for " - "event detail structure\n"); - goto fail_alloc_dma_buf; - } - - /* - * Initialize locks and queues - */ - INIT_LIST_HEAD(&instance->cmd_pool); - INIT_LIST_HEAD(&instance->internal_reset_pending_q); - - atomic_set(&instance->fw_outstanding,0); - - init_waitqueue_head(&instance->int_cmd_wait_q); - init_waitqueue_head(&instance->abort_cmd_wait_q); - - spin_lock_init(&instance->cmd_pool_lock); - spin_lock_init(&instance->hba_lock); - spin_lock_init(&instance->completion_lock); - spin_lock_init(&poll_aen_lock); - - mutex_init(&instance->aen_mutex); - - /* - * Initialize PCI related and misc parameters - */ - instance->pdev = pdev; - instance->host = host; - instance->unique_id = pdev->bus->number << 8 | pdev->devfn; - instance->init_id = MEGASAS_DEFAULT_INIT_ID; - - if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || - (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { - instance->flag_ieee = 1; - sema_init(&instance->ioctl_sem, MEGASAS_SKINNY_INT_CMDS); - } else - sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS); - - megasas_dbg_lvl = 0; - instance->flag = 0; - instance->unload = 1; - instance->last_time = 0; - instance->disableOnlineCtrlReset = 1; - - INIT_WORK(&instance->work_init, process_fw_state_change_wq); - - /* - * Initialize MFI Firmware - */ - if (megasas_init_mfi(instance)) - goto fail_init_mfi; - - /* - * Register IRQ - */ - if (request_irq(pdev->irq, megasas_isr, IRQF_SHARED, "megasas", instance)) { - printk(KERN_DEBUG "megasas: Failed to register IRQ\n"); - goto fail_irq; - } - - instance->instancet->enable_intr(instance->reg_set); - - /* - * Store instance in PCI softstate - */ - pci_set_drvdata(pdev, instance); - - /* - * Add this controller to megasas_mgmt_info structure so that it - * can be exported to management applications - */ - megasas_mgmt_info.count++; - megasas_mgmt_info.instance[megasas_mgmt_info.max_index] = instance; - megasas_mgmt_info.max_index++; - - /* - * Initiate AEN (Asynchronous Event Notification) - */ - if (megasas_start_aen(instance)) { - printk(KERN_DEBUG "megasas: start aen failed\n"); - goto fail_start_aen; - } - - /* - * Register with SCSI mid-layer - */ - if (megasas_io_attach(instance)) - goto fail_io_attach; - - instance->unload = 0; - return 0; - - fail_start_aen: - fail_io_attach: - megasas_mgmt_info.count--; - megasas_mgmt_info.instance[megasas_mgmt_info.max_index] = NULL; - megasas_mgmt_info.max_index--; - - pci_set_drvdata(pdev, NULL); - instance->instancet->disable_intr(instance->reg_set); - free_irq(instance->pdev->irq, instance); - - megasas_release_mfi(instance); - - fail_irq: - fail_init_mfi: - fail_alloc_dma_buf: - if (instance->evt_detail) - pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), - instance->evt_detail, - instance->evt_detail_h); - - if (instance->producer) - pci_free_consistent(pdev, sizeof(u32), instance->producer, - instance->producer_h); - if (instance->consumer) - pci_free_consistent(pdev, sizeof(u32), instance->consumer, - instance->consumer_h); - scsi_host_put(host); - - fail_alloc_instance: - fail_set_dma_mask: - pci_disable_device(pdev); - - return -ENODEV; -} - -/** - * megasas_flush_cache - Requests FW to flush all its caches - * @instance: Adapter soft state - */ -static void megasas_flush_cache(struct megasas_instance *instance) -{ - struct megasas_cmd *cmd; - struct megasas_dcmd_frame *dcmd; - - if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) - return; - - cmd = megasas_get_cmd(instance); - - if (!cmd) - return; - - dcmd = &cmd->frame->dcmd; - - memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); - - dcmd->cmd = MFI_CMD_DCMD; - dcmd->cmd_status = 0x0; - dcmd->sge_count = 0; - dcmd->flags = MFI_FRAME_DIR_NONE; - dcmd->timeout = 0; - dcmd->pad_0 = 0; - dcmd->data_xfer_len = 0; - dcmd->opcode = MR_DCMD_CTRL_CACHE_FLUSH; - dcmd->mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE; - - megasas_issue_blocked_cmd(instance, cmd); - - megasas_return_cmd(instance, cmd); - - return; -} - -/** - * megasas_shutdown_controller - Instructs FW to shutdown the controller - * @instance: Adapter soft state - * @opcode: Shutdown/Hibernate - */ -static void megasas_shutdown_controller(struct megasas_instance *instance, - u32 opcode) -{ - struct megasas_cmd *cmd; - struct megasas_dcmd_frame *dcmd; - - if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) - return; - - cmd = megasas_get_cmd(instance); - - if (!cmd) - return; - - if (instance->aen_cmd) - megasas_issue_blocked_abort_cmd(instance, instance->aen_cmd); - - dcmd = &cmd->frame->dcmd; - - memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); - - dcmd->cmd = MFI_CMD_DCMD; - dcmd->cmd_status = 0x0; - dcmd->sge_count = 0; - dcmd->flags = MFI_FRAME_DIR_NONE; - dcmd->timeout = 0; - dcmd->pad_0 = 0; - dcmd->data_xfer_len = 0; - dcmd->opcode = opcode; - - megasas_issue_blocked_cmd(instance, cmd); - - megasas_return_cmd(instance, cmd); - - return; -} - -#ifdef CONFIG_PM -/** - * megasas_suspend - driver suspend entry point - * @pdev: PCI device structure - * @state: PCI power state to suspend routine - */ -static int -megasas_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct Scsi_Host *host; - struct megasas_instance *instance; - - instance = pci_get_drvdata(pdev); - host = instance->host; - instance->unload = 1; - - if (poll_mode_io) - del_timer_sync(&instance->io_completion_timer); - - megasas_flush_cache(instance); - megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN); - - /* cancel the delayed work if this work still in queue */ - if (instance->ev != NULL) { - struct megasas_aen_event *ev = instance->ev; - cancel_delayed_work( - (struct delayed_work *)&ev->hotplug_work); - flush_scheduled_work(); - instance->ev = NULL; - } - - tasklet_kill(&instance->isr_tasklet); - - pci_set_drvdata(instance->pdev, instance); - instance->instancet->disable_intr(instance->reg_set); - free_irq(instance->pdev->irq, instance); - - pci_save_state(pdev); - pci_disable_device(pdev); - - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - - return 0; -} - -/** - * megasas_resume- driver resume entry point - * @pdev: PCI device structure - */ -static int -megasas_resume(struct pci_dev *pdev) -{ - int rval; - struct Scsi_Host *host; - struct megasas_instance *instance; - - instance = pci_get_drvdata(pdev); - host = instance->host; - pci_set_power_state(pdev, PCI_D0); - pci_enable_wake(pdev, PCI_D0, 0); - pci_restore_state(pdev); - - /* - * PCI prepping: enable device set bus mastering and dma mask - */ - rval = pci_enable_device_mem(pdev); - - if (rval) { - printk(KERN_ERR "megasas: Enable device failed\n"); - return rval; - } - - pci_set_master(pdev); - - if (megasas_set_dma_mask(pdev)) - goto fail_set_dma_mask; - - /* - * Initialize MFI Firmware - */ - - *instance->producer = 0; - *instance->consumer = 0; - - atomic_set(&instance->fw_outstanding, 0); - - /* - * We expect the FW state to be READY - */ - if (megasas_transition_to_ready(instance)) - goto fail_ready_state; - - if (megasas_issue_init_mfi(instance)) - goto fail_init_mfi; - - tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc, - (unsigned long)instance); - - /* - * Register IRQ - */ - if (request_irq(pdev->irq, megasas_isr, IRQF_SHARED, - "megasas", instance)) { - printk(KERN_ERR "megasas: Failed to register IRQ\n"); - goto fail_irq; - } - - instance->instancet->enable_intr(instance->reg_set); - - /* - * Initiate AEN (Asynchronous Event Notification) - */ - if (megasas_start_aen(instance)) - printk(KERN_ERR "megasas: Start AEN failed\n"); - - /* Initialize the cmd completion timer */ - if (poll_mode_io) - megasas_start_timer(instance, &instance->io_completion_timer, - megasas_io_completion_timer, - MEGASAS_COMPLETION_TIMER_INTERVAL); - instance->unload = 0; - - return 0; - -fail_irq: -fail_init_mfi: - if (instance->evt_detail) - pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), - instance->evt_detail, - instance->evt_detail_h); - - if (instance->producer) - pci_free_consistent(pdev, sizeof(u32), instance->producer, - instance->producer_h); - if (instance->consumer) - pci_free_consistent(pdev, sizeof(u32), instance->consumer, - instance->consumer_h); - scsi_host_put(host); - -fail_set_dma_mask: -fail_ready_state: - - pci_disable_device(pdev); - - return -ENODEV; -} -#else -#define megasas_suspend NULL -#define megasas_resume NULL -#endif - -/** - * megasas_detach_one - PCI hot"un"plug entry point - * @pdev: PCI device structure - */ -static void __devexit megasas_detach_one(struct pci_dev *pdev) -{ - int i; - struct Scsi_Host *host; - struct megasas_instance *instance; - - instance = pci_get_drvdata(pdev); - instance->unload = 1; - host = instance->host; - - if (poll_mode_io) - del_timer_sync(&instance->io_completion_timer); - - scsi_remove_host(instance->host); - megasas_flush_cache(instance); - megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); - - /* cancel the delayed work if this work still in queue*/ - if (instance->ev != NULL) { - struct megasas_aen_event *ev = instance->ev; - cancel_delayed_work( - (struct delayed_work *)&ev->hotplug_work); - flush_scheduled_work(); - instance->ev = NULL; - } - - tasklet_kill(&instance->isr_tasklet); - - /* - * Take the instance off the instance array. Note that we will not - * decrement the max_index. We let this array be sparse array - */ - for (i = 0; i < megasas_mgmt_info.max_index; i++) { - if (megasas_mgmt_info.instance[i] == instance) { - megasas_mgmt_info.count--; - megasas_mgmt_info.instance[i] = NULL; - - break; - } - } - - pci_set_drvdata(instance->pdev, NULL); - - instance->instancet->disable_intr(instance->reg_set); - - free_irq(instance->pdev->irq, instance); - - megasas_release_mfi(instance); - - pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), - instance->evt_detail, instance->evt_detail_h); - - pci_free_consistent(pdev, sizeof(u32), instance->producer, - instance->producer_h); - - pci_free_consistent(pdev, sizeof(u32), instance->consumer, - instance->consumer_h); - - scsi_host_put(host); - - pci_set_drvdata(pdev, NULL); - - pci_disable_device(pdev); - - return; -} - -/** - * megasas_shutdown - Shutdown entry point - * @device: Generic device structure - */ -static void megasas_shutdown(struct pci_dev *pdev) -{ - struct megasas_instance *instance = pci_get_drvdata(pdev); - instance->unload = 1; - megasas_flush_cache(instance); - megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); -} - -/** - * megasas_mgmt_open - char node "open" entry point - */ -static int megasas_mgmt_open(struct inode *inode, struct file *filep) -{ - /* - * Allow only those users with admin rights - */ - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - - return 0; -} - -/** - * megasas_mgmt_fasync - Async notifier registration from applications - * - * This function adds the calling process to a driver global queue. When an - * event occurs, SIGIO will be sent to all processes in this queue. - */ -static int megasas_mgmt_fasync(int fd, struct file *filep, int mode) -{ - int rc; - - mutex_lock(&megasas_async_queue_mutex); - - rc = fasync_helper(fd, filep, mode, &megasas_async_queue); - - mutex_unlock(&megasas_async_queue_mutex); - - if (rc >= 0) { - /* For sanity check when we get ioctl */ - filep->private_data = filep; - return 0; - } - - printk(KERN_DEBUG "megasas: fasync_helper failed [%d]\n", rc); - - return rc; -} - -/** - * megasas_mgmt_poll - char node "poll" entry point - * */ -static unsigned int megasas_mgmt_poll(struct file *file, poll_table *wait) -{ - unsigned int mask; - unsigned long flags; - poll_wait(file, &megasas_poll_wait, wait); - spin_lock_irqsave(&poll_aen_lock, flags); - if (megasas_poll_wait_aen) - mask = (POLLIN | POLLRDNORM); - else - mask = 0; - spin_unlock_irqrestore(&poll_aen_lock, flags); - return mask; -} - -/** - * megasas_mgmt_fw_ioctl - Issues management ioctls to FW - * @instance: Adapter soft state - * @argp: User's ioctl packet - */ -static int -megasas_mgmt_fw_ioctl(struct megasas_instance *instance, - struct megasas_iocpacket __user * user_ioc, - struct megasas_iocpacket *ioc) -{ - struct megasas_sge32 *kern_sge32; - struct megasas_cmd *cmd; - void *kbuff_arr[MAX_IOCTL_SGE]; - dma_addr_t buf_handle = 0; - int error = 0, i; - void *sense = NULL; - dma_addr_t sense_handle; - unsigned long *sense_ptr; - - memset(kbuff_arr, 0, sizeof(kbuff_arr)); - - if (ioc->sge_count > MAX_IOCTL_SGE) { - printk(KERN_DEBUG "megasas: SGE count [%d] > max limit [%d]\n", - ioc->sge_count, MAX_IOCTL_SGE); - return -EINVAL; - } - - cmd = megasas_get_cmd(instance); - if (!cmd) { - printk(KERN_DEBUG "megasas: Failed to get a cmd packet\n"); - return -ENOMEM; - } - - /* - * User's IOCTL packet has 2 frames (maximum). Copy those two - * frames into our cmd's frames. cmd->frame's context will get - * overwritten when we copy from user's frames. So set that value - * alone separately - */ - memcpy(cmd->frame, ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE); - cmd->frame->hdr.context = cmd->index; - cmd->frame->hdr.pad_0 = 0; - - /* - * The management interface between applications and the fw uses - * MFI frames. E.g, RAID configuration changes, LD property changes - * etc are accomplishes through different kinds of MFI frames. The - * driver needs to care only about substituting user buffers with - * kernel buffers in SGLs. The location of SGL is embedded in the - * struct iocpacket itself. - */ - kern_sge32 = (struct megasas_sge32 *) - ((unsigned long)cmd->frame + ioc->sgl_off); - - /* - * For each user buffer, create a mirror buffer and copy in - */ - for (i = 0; i < ioc->sge_count; i++) { - kbuff_arr[i] = dma_alloc_coherent(&instance->pdev->dev, - ioc->sgl[i].iov_len, - &buf_handle, GFP_KERNEL); - if (!kbuff_arr[i]) { - printk(KERN_DEBUG "megasas: Failed to alloc " - "kernel SGL buffer for IOCTL \n"); - error = -ENOMEM; - goto out; - } - - /* - * We don't change the dma_coherent_mask, so - * pci_alloc_consistent only returns 32bit addresses - */ - kern_sge32[i].phys_addr = (u32) buf_handle; - kern_sge32[i].length = ioc->sgl[i].iov_len; - - /* - * We created a kernel buffer corresponding to the - * user buffer. Now copy in from the user buffer - */ - if (copy_from_user(kbuff_arr[i], ioc->sgl[i].iov_base, - (u32) (ioc->sgl[i].iov_len))) { - error = -EFAULT; - goto out; - } - } - - if (ioc->sense_len) { - sense = dma_alloc_coherent(&instance->pdev->dev, ioc->sense_len, - &sense_handle, GFP_KERNEL); - if (!sense) { - error = -ENOMEM; - goto out; - } - - sense_ptr = - (unsigned long *) ((unsigned long)cmd->frame + ioc->sense_off); - *sense_ptr = sense_handle; - } - - /* - * Set the sync_cmd flag so that the ISR knows not to complete this - * cmd to the SCSI mid-layer - */ - cmd->sync_cmd = 1; - megasas_issue_blocked_cmd(instance, cmd); - cmd->sync_cmd = 0; - - /* - * copy out the kernel buffers to user buffers - */ - for (i = 0; i < ioc->sge_count; i++) { - if (copy_to_user(ioc->sgl[i].iov_base, kbuff_arr[i], - ioc->sgl[i].iov_len)) { - error = -EFAULT; - goto out; - } - } - - /* - * copy out the sense - */ - if (ioc->sense_len) { - /* - * sense_ptr points to the location that has the user - * sense buffer address - */ - sense_ptr = (unsigned long *) ((unsigned long)ioc->frame.raw + - ioc->sense_off); - - if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)), - sense, ioc->sense_len)) { - printk(KERN_ERR "megasas: Failed to copy out to user " - "sense data\n"); - error = -EFAULT; - goto out; - } - } - - /* - * copy the status codes returned by the fw - */ - if (copy_to_user(&user_ioc->frame.hdr.cmd_status, - &cmd->frame->hdr.cmd_status, sizeof(u8))) { - printk(KERN_DEBUG "megasas: Error copying out cmd_status\n"); - error = -EFAULT; - } - - out: - if (sense) { - dma_free_coherent(&instance->pdev->dev, ioc->sense_len, - sense, sense_handle); - } - - for (i = 0; i < ioc->sge_count && kbuff_arr[i]; i++) { - dma_free_coherent(&instance->pdev->dev, - kern_sge32[i].length, - kbuff_arr[i], kern_sge32[i].phys_addr); - } - - megasas_return_cmd(instance, cmd); - return error; -} - -static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg) -{ - struct megasas_iocpacket __user *user_ioc = - (struct megasas_iocpacket __user *)arg; - struct megasas_iocpacket *ioc; - struct megasas_instance *instance; - int error; - int i; - unsigned long flags; - u32 wait_time = MEGASAS_RESET_WAIT_TIME; - - ioc = kmalloc(sizeof(*ioc), GFP_KERNEL); - if (!ioc) - return -ENOMEM; - - if (copy_from_user(ioc, user_ioc, sizeof(*ioc))) { - error = -EFAULT; - goto out_kfree_ioc; - } - - instance = megasas_lookup_instance(ioc->host_no); - if (!instance) { - error = -ENODEV; - goto out_kfree_ioc; - } - - if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) { - printk(KERN_ERR "Controller in crit error\n"); - error = -ENODEV; - goto out_kfree_ioc; - } - - if (instance->unload == 1) { - error = -ENODEV; - goto out_kfree_ioc; - } - - /* - * We will allow only MEGASAS_INT_CMDS number of parallel ioctl cmds - */ - if (down_interruptible(&instance->ioctl_sem)) { - error = -ERESTARTSYS; - goto out_kfree_ioc; - } - - for (i = 0; i < wait_time; i++) { - - spin_lock_irqsave(&instance->hba_lock, flags); - if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) { - spin_unlock_irqrestore(&instance->hba_lock, flags); - break; - } - spin_unlock_irqrestore(&instance->hba_lock, flags); - - if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { - printk(KERN_NOTICE "megasas: waiting" - "for controller reset to finish\n"); - } - - msleep(1000); - } - - spin_lock_irqsave(&instance->hba_lock, flags); - if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) { - spin_unlock_irqrestore(&instance->hba_lock, flags); - - printk(KERN_ERR "megaraid_sas: timed out while" - "waiting for HBA to recover\n"); - error = -ENODEV; - goto out_kfree_ioc; - } - spin_unlock_irqrestore(&instance->hba_lock, flags); - - error = megasas_mgmt_fw_ioctl(instance, user_ioc, ioc); - up(&instance->ioctl_sem); - - out_kfree_ioc: - kfree(ioc); - return error; -} - -static int megasas_mgmt_ioctl_aen(struct file *file, unsigned long arg) -{ - struct megasas_instance *instance; - struct megasas_aen aen; - int error; - int i; - unsigned long flags; - u32 wait_time = MEGASAS_RESET_WAIT_TIME; - - if (file->private_data != file) { - printk(KERN_DEBUG "megasas: fasync_helper was not " - "called first\n"); - return -EINVAL; - } - - if (copy_from_user(&aen, (void __user *)arg, sizeof(aen))) - return -EFAULT; - - instance = megasas_lookup_instance(aen.host_no); - - if (!instance) - return -ENODEV; - - if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) { - return -ENODEV; - } - - if (instance->unload == 1) { - return -ENODEV; - } - - for (i = 0; i < wait_time; i++) { - - spin_lock_irqsave(&instance->hba_lock, flags); - if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) { - spin_unlock_irqrestore(&instance->hba_lock, - flags); - break; - } - - spin_unlock_irqrestore(&instance->hba_lock, flags); - - if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { - printk(KERN_NOTICE "megasas: waiting for" - "controller reset to finish\n"); - } - - msleep(1000); - } - - spin_lock_irqsave(&instance->hba_lock, flags); - if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) { - spin_unlock_irqrestore(&instance->hba_lock, flags); - printk(KERN_ERR "megaraid_sas: timed out while waiting" - "for HBA to recover.\n"); - return -ENODEV; - } - spin_unlock_irqrestore(&instance->hba_lock, flags); - - mutex_lock(&instance->aen_mutex); - error = megasas_register_aen(instance, aen.seq_num, - aen.class_locale_word); - mutex_unlock(&instance->aen_mutex); - return error; -} - -/** - * megasas_mgmt_ioctl - char node ioctl entry point - */ -static long -megasas_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case MEGASAS_IOC_FIRMWARE: - return megasas_mgmt_ioctl_fw(file, arg); - - case MEGASAS_IOC_GET_AEN: - return megasas_mgmt_ioctl_aen(file, arg); - } - - return -ENOTTY; -} - -#ifdef CONFIG_COMPAT -static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg) -{ - struct compat_megasas_iocpacket __user *cioc = - (struct compat_megasas_iocpacket __user *)arg; - struct megasas_iocpacket __user *ioc = - compat_alloc_user_space(sizeof(struct megasas_iocpacket)); - int i; - int error = 0; - compat_uptr_t ptr; - - if (clear_user(ioc, sizeof(*ioc))) - return -EFAULT; - - if (copy_in_user(&ioc->host_no, &cioc->host_no, sizeof(u16)) || - copy_in_user(&ioc->sgl_off, &cioc->sgl_off, sizeof(u32)) || - copy_in_user(&ioc->sense_off, &cioc->sense_off, sizeof(u32)) || - copy_in_user(&ioc->sense_len, &cioc->sense_len, sizeof(u32)) || - copy_in_user(ioc->frame.raw, cioc->frame.raw, 128) || - copy_in_user(&ioc->sge_count, &cioc->sge_count, sizeof(u32))) - return -EFAULT; - - /* - * The sense_ptr is used in megasas_mgmt_fw_ioctl only when - * sense_len is not null, so prepare the 64bit value under - * the same condition. - */ - if (ioc->sense_len) { - void __user **sense_ioc_ptr = - (void __user **)(ioc->frame.raw + ioc->sense_off); - compat_uptr_t *sense_cioc_ptr = - (compat_uptr_t *)(cioc->frame.raw + cioc->sense_off); - if (get_user(ptr, sense_cioc_ptr) || - put_user(compat_ptr(ptr), sense_ioc_ptr)) - return -EFAULT; - } - - for (i = 0; i < MAX_IOCTL_SGE; i++) { - if (get_user(ptr, &cioc->sgl[i].iov_base) || - put_user(compat_ptr(ptr), &ioc->sgl[i].iov_base) || - copy_in_user(&ioc->sgl[i].iov_len, - &cioc->sgl[i].iov_len, sizeof(compat_size_t))) - return -EFAULT; - } - - error = megasas_mgmt_ioctl_fw(file, (unsigned long)ioc); - - if (copy_in_user(&cioc->frame.hdr.cmd_status, - &ioc->frame.hdr.cmd_status, sizeof(u8))) { - printk(KERN_DEBUG "megasas: error copy_in_user cmd_status\n"); - return -EFAULT; - } - return error; -} - -static long -megasas_mgmt_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - switch (cmd) { - case MEGASAS_IOC_FIRMWARE32: - return megasas_mgmt_compat_ioctl_fw(file, arg); - case MEGASAS_IOC_GET_AEN: - return megasas_mgmt_ioctl_aen(file, arg); - } - - return -ENOTTY; -} -#endif - -/* - * File operations structure for management interface - */ -static const struct file_operations megasas_mgmt_fops = { - .owner = THIS_MODULE, - .open = megasas_mgmt_open, - .fasync = megasas_mgmt_fasync, - .unlocked_ioctl = megasas_mgmt_ioctl, - .poll = megasas_mgmt_poll, -#ifdef CONFIG_COMPAT - .compat_ioctl = megasas_mgmt_compat_ioctl, -#endif - .llseek = noop_llseek, -}; - -/* - * PCI hotplug support registration structure - */ -static struct pci_driver megasas_pci_driver = { - - .name = "megaraid_sas", - .id_table = megasas_pci_table, - .probe = megasas_probe_one, - .remove = __devexit_p(megasas_detach_one), - .suspend = megasas_suspend, - .resume = megasas_resume, - .shutdown = megasas_shutdown, -}; - -/* - * Sysfs driver attributes - */ -static ssize_t megasas_sysfs_show_version(struct device_driver *dd, char *buf) -{ - return snprintf(buf, strlen(MEGASAS_VERSION) + 2, "%s\n", - MEGASAS_VERSION); -} - -static DRIVER_ATTR(version, S_IRUGO, megasas_sysfs_show_version, NULL); - -static ssize_t -megasas_sysfs_show_release_date(struct device_driver *dd, char *buf) -{ - return snprintf(buf, strlen(MEGASAS_RELDATE) + 2, "%s\n", - MEGASAS_RELDATE); -} - -static DRIVER_ATTR(release_date, S_IRUGO, megasas_sysfs_show_release_date, - NULL); - -static ssize_t -megasas_sysfs_show_support_poll_for_event(struct device_driver *dd, char *buf) -{ - return sprintf(buf, "%u\n", support_poll_for_event); -} - -static DRIVER_ATTR(support_poll_for_event, S_IRUGO, - megasas_sysfs_show_support_poll_for_event, NULL); - - static ssize_t -megasas_sysfs_show_support_device_change(struct device_driver *dd, char *buf) -{ - return sprintf(buf, "%u\n", support_device_change); -} - -static DRIVER_ATTR(support_device_change, S_IRUGO, - megasas_sysfs_show_support_device_change, NULL); - -static ssize_t -megasas_sysfs_show_dbg_lvl(struct device_driver *dd, char *buf) -{ - return sprintf(buf, "%u\n", megasas_dbg_lvl); -} - -static ssize_t -megasas_sysfs_set_dbg_lvl(struct device_driver *dd, const char *buf, size_t count) -{ - int retval = count; - if(sscanf(buf,"%u",&megasas_dbg_lvl)<1){ - printk(KERN_ERR "megasas: could not set dbg_lvl\n"); - retval = -EINVAL; - } - return retval; -} - -static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUSR, megasas_sysfs_show_dbg_lvl, - megasas_sysfs_set_dbg_lvl); - -static ssize_t -megasas_sysfs_show_poll_mode_io(struct device_driver *dd, char *buf) -{ - return sprintf(buf, "%u\n", poll_mode_io); -} - -static ssize_t -megasas_sysfs_set_poll_mode_io(struct device_driver *dd, - const char *buf, size_t count) -{ - int retval = count; - int tmp = poll_mode_io; - int i; - struct megasas_instance *instance; - - if (sscanf(buf, "%u", &poll_mode_io) < 1) { - printk(KERN_ERR "megasas: could not set poll_mode_io\n"); - retval = -EINVAL; - } - - /* - * Check if poll_mode_io is already set or is same as previous value - */ - if ((tmp && poll_mode_io) || (tmp == poll_mode_io)) - goto out; - - if (poll_mode_io) { - /* - * Start timers for all adapters - */ - for (i = 0; i < megasas_mgmt_info.max_index; i++) { - instance = megasas_mgmt_info.instance[i]; - if (instance) { - megasas_start_timer(instance, - &instance->io_completion_timer, - megasas_io_completion_timer, - MEGASAS_COMPLETION_TIMER_INTERVAL); - } - } - } else { - /* - * Delete timers for all adapters - */ - for (i = 0; i < megasas_mgmt_info.max_index; i++) { - instance = megasas_mgmt_info.instance[i]; - if (instance) - del_timer_sync(&instance->io_completion_timer); - } - } - -out: - return retval; -} - -static void -megasas_aen_polling(struct work_struct *work) -{ - struct megasas_aen_event *ev = - container_of(work, struct megasas_aen_event, hotplug_work); - struct megasas_instance *instance = ev->instance; - union megasas_evt_class_locale class_locale; - struct Scsi_Host *host; - struct scsi_device *sdev1; - u16 pd_index = 0; - u16 ld_index = 0; - int i, j, doscan = 0; - u32 seq_num; - int error; - - if (!instance) { - printk(KERN_ERR "invalid instance!\n"); - kfree(ev); - return; - } - instance->ev = NULL; - host = instance->host; - if (instance->evt_detail) { - - switch (instance->evt_detail->code) { - case MR_EVT_PD_INSERTED: - if (megasas_get_pd_list(instance) == 0) { - for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) { - for (j = 0; - j < MEGASAS_MAX_DEV_PER_CHANNEL; - j++) { - - pd_index = - (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; - - sdev1 = - scsi_device_lookup(host, i, j, 0); - - if (instance->pd_list[pd_index].driveState - == MR_PD_STATE_SYSTEM) { - if (!sdev1) { - scsi_add_device(host, i, j, 0); - } - - if (sdev1) - scsi_device_put(sdev1); - } - } - } - } - doscan = 0; - break; - - case MR_EVT_PD_REMOVED: - if (megasas_get_pd_list(instance) == 0) { - megasas_get_pd_list(instance); - for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) { - for (j = 0; - j < MEGASAS_MAX_DEV_PER_CHANNEL; - j++) { - - pd_index = - (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; - - sdev1 = - scsi_device_lookup(host, i, j, 0); - - if (instance->pd_list[pd_index].driveState - == MR_PD_STATE_SYSTEM) { - if (sdev1) { - scsi_device_put(sdev1); - } - } else { - if (sdev1) { - scsi_remove_device(sdev1); - scsi_device_put(sdev1); - } - } - } - } - } - doscan = 0; - break; - - case MR_EVT_LD_OFFLINE: - case MR_EVT_LD_DELETED: - megasas_get_ld_list(instance); - for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { - for (j = 0; - j < MEGASAS_MAX_DEV_PER_CHANNEL; - j++) { - - ld_index = - (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; - - sdev1 = scsi_device_lookup(host, - i + MEGASAS_MAX_LD_CHANNELS, - j, - 0); - - if (instance->ld_ids[ld_index] != 0xff) { - if (sdev1) { - scsi_device_put(sdev1); - } - } else { - if (sdev1) { - scsi_remove_device(sdev1); - scsi_device_put(sdev1); - } - } - } - } - doscan = 0; - break; - case MR_EVT_LD_CREATED: - megasas_get_ld_list(instance); - for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { - for (j = 0; - j < MEGASAS_MAX_DEV_PER_CHANNEL; - j++) { - ld_index = - (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; - - sdev1 = scsi_device_lookup(host, - i+MEGASAS_MAX_LD_CHANNELS, - j, 0); - - if (instance->ld_ids[ld_index] != - 0xff) { - if (!sdev1) { - scsi_add_device(host, - i + 2, - j, 0); - } - } - if (sdev1) { - scsi_device_put(sdev1); - } - } - } - doscan = 0; - break; - case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED: - case MR_EVT_FOREIGN_CFG_IMPORTED: - doscan = 1; - break; - default: - doscan = 0; - break; - } - } else { - printk(KERN_ERR "invalid evt_detail!\n"); - kfree(ev); - return; - } - - if (doscan) { - printk(KERN_INFO "scanning ...\n"); - megasas_get_pd_list(instance); - for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) { - for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) { - pd_index = i*MEGASAS_MAX_DEV_PER_CHANNEL + j; - sdev1 = scsi_device_lookup(host, i, j, 0); - if (instance->pd_list[pd_index].driveState == - MR_PD_STATE_SYSTEM) { - if (!sdev1) { - scsi_add_device(host, i, j, 0); - } - if (sdev1) - scsi_device_put(sdev1); - } else { - if (sdev1) { - scsi_remove_device(sdev1); - scsi_device_put(sdev1); - } - } - } - } - - megasas_get_ld_list(instance); - for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { - for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) { - ld_index = - (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; - - sdev1 = scsi_device_lookup(host, - i+MEGASAS_MAX_LD_CHANNELS, j, 0); - if (instance->ld_ids[ld_index] != 0xff) { - if (!sdev1) { - scsi_add_device(host, - i+2, - j, 0); - } else { - scsi_device_put(sdev1); - } - } else { - if (sdev1) { - scsi_remove_device(sdev1); - scsi_device_put(sdev1); - } - } - } - } - } - - if ( instance->aen_cmd != NULL ) { - kfree(ev); - return ; - } - - seq_num = instance->evt_detail->seq_num + 1; - - /* Register AEN with FW for latest sequence number plus 1 */ - class_locale.members.reserved = 0; - class_locale.members.locale = MR_EVT_LOCALE_ALL; - class_locale.members.class = MR_EVT_CLASS_DEBUG; - mutex_lock(&instance->aen_mutex); - error = megasas_register_aen(instance, seq_num, - class_locale.word); - mutex_unlock(&instance->aen_mutex); - - if (error) - printk(KERN_ERR "register aen failed error %x\n", error); - - kfree(ev); -} - - -static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUSR, - megasas_sysfs_show_poll_mode_io, - megasas_sysfs_set_poll_mode_io); - -/** - * megasas_init - Driver load entry point - */ -static int __init megasas_init(void) -{ - int rval; - - /* - * Announce driver version and other information - */ - printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION, - MEGASAS_EXT_VERSION); - - support_poll_for_event = 2; - support_device_change = 1; - - memset(&megasas_mgmt_info, 0, sizeof(megasas_mgmt_info)); - - /* - * Register character device node - */ - rval = register_chrdev(0, "megaraid_sas_ioctl", &megasas_mgmt_fops); - - if (rval < 0) { - printk(KERN_DEBUG "megasas: failed to open device node\n"); - return rval; - } - - megasas_mgmt_majorno = rval; - - /* - * Register ourselves as PCI hotplug module - */ - rval = pci_register_driver(&megasas_pci_driver); - - if (rval) { - printk(KERN_DEBUG "megasas: PCI hotplug regisration failed \n"); - goto err_pcidrv; - } - - rval = driver_create_file(&megasas_pci_driver.driver, - &driver_attr_version); - if (rval) - goto err_dcf_attr_ver; - rval = driver_create_file(&megasas_pci_driver.driver, - &driver_attr_release_date); - if (rval) - goto err_dcf_rel_date; - - rval = driver_create_file(&megasas_pci_driver.driver, - &driver_attr_support_poll_for_event); - if (rval) - goto err_dcf_support_poll_for_event; - - rval = driver_create_file(&megasas_pci_driver.driver, - &driver_attr_dbg_lvl); - if (rval) - goto err_dcf_dbg_lvl; - rval = driver_create_file(&megasas_pci_driver.driver, - &driver_attr_poll_mode_io); - if (rval) - goto err_dcf_poll_mode_io; - - rval = driver_create_file(&megasas_pci_driver.driver, - &driver_attr_support_device_change); - if (rval) - goto err_dcf_support_device_change; - - return rval; - -err_dcf_support_device_change: - driver_remove_file(&megasas_pci_driver.driver, - &driver_attr_poll_mode_io); - -err_dcf_poll_mode_io: - driver_remove_file(&megasas_pci_driver.driver, - &driver_attr_dbg_lvl); -err_dcf_dbg_lvl: - driver_remove_file(&megasas_pci_driver.driver, - &driver_attr_support_poll_for_event); - -err_dcf_support_poll_for_event: - driver_remove_file(&megasas_pci_driver.driver, - &driver_attr_release_date); - -err_dcf_rel_date: - driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version); -err_dcf_attr_ver: - pci_unregister_driver(&megasas_pci_driver); -err_pcidrv: - unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl"); - return rval; -} - -/** - * megasas_exit - Driver unload entry point - */ -static void __exit megasas_exit(void) -{ - driver_remove_file(&megasas_pci_driver.driver, - &driver_attr_poll_mode_io); - driver_remove_file(&megasas_pci_driver.driver, - &driver_attr_dbg_lvl); - driver_remove_file(&megasas_pci_driver.driver, - &driver_attr_support_poll_for_event); - driver_remove_file(&megasas_pci_driver.driver, - &driver_attr_support_device_change); - driver_remove_file(&megasas_pci_driver.driver, - &driver_attr_release_date); - driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version); - - pci_unregister_driver(&megasas_pci_driver); - unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl"); -} - -module_init(megasas_init); -module_exit(megasas_exit); diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c new file mode 100644 index 000000000000..427f0f795947 --- /dev/null +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -0,0 +1,5193 @@ +/* + * + * Linux MegaRAID driver for SAS based RAID controllers + * + * Copyright (c) 2003-2005 LSI Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * FILE : megaraid_sas.c + * Version : v00.00.04.31-rc1 + * + * Authors: + * (email-id : megaraidlinux@lsi.com) + * Sreenivas Bagalkote + * Sumant Patro + * Bo Yang + * + * List of supported controllers + * + * OEM Product Name VID DID SSVID SSID + * --- ------------ --- --- ---- ---- + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "megaraid_sas.h" + +/* + * poll_mode_io:1- schedule complete completion from q cmd + */ +static unsigned int poll_mode_io; +module_param_named(poll_mode_io, poll_mode_io, int, 0); +MODULE_PARM_DESC(poll_mode_io, + "Complete cmds from IO path, (default=0)"); + +/* + * Number of sectors per IO command + * Will be set in megasas_init_mfi if user does not provide + */ +static unsigned int max_sectors; +module_param_named(max_sectors, max_sectors, int, 0); +MODULE_PARM_DESC(max_sectors, + "Maximum number of sectors per IO command"); + +MODULE_LICENSE("GPL"); +MODULE_VERSION(MEGASAS_VERSION); +MODULE_AUTHOR("megaraidlinux@lsi.com"); +MODULE_DESCRIPTION("LSI MegaRAID SAS Driver"); + +static int megasas_transition_to_ready(struct megasas_instance *instance); +static int megasas_get_pd_list(struct megasas_instance *instance); +static int megasas_issue_init_mfi(struct megasas_instance *instance); +static int megasas_register_aen(struct megasas_instance *instance, + u32 seq_num, u32 class_locale_word); +/* + * PCI ID table for all supported controllers + */ +static struct pci_device_id megasas_pci_table[] = { + + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064R)}, + /* xscale IOP */ + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078R)}, + /* ppc IOP */ + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078DE)}, + /* ppc IOP */ + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078GEN2)}, + /* gen2*/ + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0079GEN2)}, + /* gen2*/ + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0073SKINNY)}, + /* skinny*/ + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0071SKINNY)}, + /* skinny*/ + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)}, + /* xscale IOP, vega */ + {PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)}, + /* xscale IOP */ + {} +}; + +MODULE_DEVICE_TABLE(pci, megasas_pci_table); + +static int megasas_mgmt_majorno; +static struct megasas_mgmt_info megasas_mgmt_info; +static struct fasync_struct *megasas_async_queue; +static DEFINE_MUTEX(megasas_async_queue_mutex); + +static int megasas_poll_wait_aen; +static DECLARE_WAIT_QUEUE_HEAD(megasas_poll_wait); +static u32 support_poll_for_event; +static u32 megasas_dbg_lvl; +static u32 support_device_change; + +/* define lock for aen poll */ +spinlock_t poll_aen_lock; + +static void +megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, + u8 alt_status); + +/** + * megasas_get_cmd - Get a command from the free pool + * @instance: Adapter soft state + * + * Returns a free command from the pool + */ +static struct megasas_cmd *megasas_get_cmd(struct megasas_instance + *instance) +{ + unsigned long flags; + struct megasas_cmd *cmd = NULL; + + spin_lock_irqsave(&instance->cmd_pool_lock, flags); + + if (!list_empty(&instance->cmd_pool)) { + cmd = list_entry((&instance->cmd_pool)->next, + struct megasas_cmd, list); + list_del_init(&cmd->list); + } else { + printk(KERN_ERR "megasas: Command pool empty!\n"); + } + + spin_unlock_irqrestore(&instance->cmd_pool_lock, flags); + return cmd; +} + +/** + * megasas_return_cmd - Return a cmd to free command pool + * @instance: Adapter soft state + * @cmd: Command packet to be returned to free command pool + */ +static inline void +megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) +{ + unsigned long flags; + + spin_lock_irqsave(&instance->cmd_pool_lock, flags); + + cmd->scmd = NULL; + list_add_tail(&cmd->list, &instance->cmd_pool); + + spin_unlock_irqrestore(&instance->cmd_pool_lock, flags); +} + + +/** +* The following functions are defined for xscale +* (deviceid : 1064R, PERC5) controllers +*/ + +/** + * megasas_enable_intr_xscale - Enables interrupts + * @regs: MFI register set + */ +static inline void +megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs) +{ + writel(0, &(regs)->outbound_intr_mask); + + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_mask); +} + +/** + * megasas_disable_intr_xscale -Disables interrupt + * @regs: MFI register set + */ +static inline void +megasas_disable_intr_xscale(struct megasas_register_set __iomem * regs) +{ + u32 mask = 0x1f; + writel(mask, ®s->outbound_intr_mask); + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_mask); +} + +/** + * megasas_read_fw_status_reg_xscale - returns the current FW status value + * @regs: MFI register set + */ +static u32 +megasas_read_fw_status_reg_xscale(struct megasas_register_set __iomem * regs) +{ + return readl(&(regs)->outbound_msg_0); +} +/** + * megasas_clear_interrupt_xscale - Check & clear interrupt + * @regs: MFI register set + */ +static int +megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs) +{ + u32 status; + u32 mfiStatus = 0; + /* + * Check if it is our interrupt + */ + status = readl(®s->outbound_intr_status); + + if (status & MFI_OB_INTR_STATUS_MASK) + mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE; + if (status & MFI_XSCALE_OMR0_CHANGE_INTERRUPT) + mfiStatus |= MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE; + + /* + * Clear the interrupt by writing back the same value + */ + if (mfiStatus) + writel(status, ®s->outbound_intr_status); + + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_status); + + return mfiStatus; +} + +/** + * megasas_fire_cmd_xscale - Sends command to the FW + * @frame_phys_addr : Physical address of cmd + * @frame_count : Number of frames for the command + * @regs : MFI register set + */ +static inline void +megasas_fire_cmd_xscale(struct megasas_instance *instance, + dma_addr_t frame_phys_addr, + u32 frame_count, + struct megasas_register_set __iomem *regs) +{ + unsigned long flags; + spin_lock_irqsave(&instance->hba_lock, flags); + writel((frame_phys_addr >> 3)|(frame_count), + &(regs)->inbound_queue_port); + spin_unlock_irqrestore(&instance->hba_lock, flags); +} + +/** + * megasas_adp_reset_xscale - For controller reset + * @regs: MFI register set + */ +static int +megasas_adp_reset_xscale(struct megasas_instance *instance, + struct megasas_register_set __iomem *regs) +{ + u32 i; + u32 pcidata; + writel(MFI_ADP_RESET, ®s->inbound_doorbell); + + for (i = 0; i < 3; i++) + msleep(1000); /* sleep for 3 secs */ + pcidata = 0; + pci_read_config_dword(instance->pdev, MFI_1068_PCSR_OFFSET, &pcidata); + printk(KERN_NOTICE "pcidata = %x\n", pcidata); + if (pcidata & 0x2) { + printk(KERN_NOTICE "mfi 1068 offset read=%x\n", pcidata); + pcidata &= ~0x2; + pci_write_config_dword(instance->pdev, + MFI_1068_PCSR_OFFSET, pcidata); + + for (i = 0; i < 2; i++) + msleep(1000); /* need to wait 2 secs again */ + + pcidata = 0; + pci_read_config_dword(instance->pdev, + MFI_1068_FW_HANDSHAKE_OFFSET, &pcidata); + printk(KERN_NOTICE "1068 offset handshake read=%x\n", pcidata); + if ((pcidata & 0xffff0000) == MFI_1068_FW_READY) { + printk(KERN_NOTICE "1068 offset pcidt=%x\n", pcidata); + pcidata = 0; + pci_write_config_dword(instance->pdev, + MFI_1068_FW_HANDSHAKE_OFFSET, pcidata); + } + } + return 0; +} + +/** + * megasas_check_reset_xscale - For controller reset check + * @regs: MFI register set + */ +static int +megasas_check_reset_xscale(struct megasas_instance *instance, + struct megasas_register_set __iomem *regs) +{ + u32 consumer; + consumer = *instance->consumer; + + if ((instance->adprecovery != MEGASAS_HBA_OPERATIONAL) && + (*instance->consumer == MEGASAS_ADPRESET_INPROG_SIGN)) { + return 1; + } + return 0; +} + +static struct megasas_instance_template megasas_instance_template_xscale = { + + .fire_cmd = megasas_fire_cmd_xscale, + .enable_intr = megasas_enable_intr_xscale, + .disable_intr = megasas_disable_intr_xscale, + .clear_intr = megasas_clear_intr_xscale, + .read_fw_status_reg = megasas_read_fw_status_reg_xscale, + .adp_reset = megasas_adp_reset_xscale, + .check_reset = megasas_check_reset_xscale, +}; + +/** +* This is the end of set of functions & definitions specific +* to xscale (deviceid : 1064R, PERC5) controllers +*/ + +/** +* The following functions are defined for ppc (deviceid : 0x60) +* controllers +*/ + +/** + * megasas_enable_intr_ppc - Enables interrupts + * @regs: MFI register set + */ +static inline void +megasas_enable_intr_ppc(struct megasas_register_set __iomem * regs) +{ + writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear); + + writel(~0x80000000, &(regs)->outbound_intr_mask); + + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_mask); +} + +/** + * megasas_disable_intr_ppc - Disable interrupt + * @regs: MFI register set + */ +static inline void +megasas_disable_intr_ppc(struct megasas_register_set __iomem * regs) +{ + u32 mask = 0xFFFFFFFF; + writel(mask, ®s->outbound_intr_mask); + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_mask); +} + +/** + * megasas_read_fw_status_reg_ppc - returns the current FW status value + * @regs: MFI register set + */ +static u32 +megasas_read_fw_status_reg_ppc(struct megasas_register_set __iomem * regs) +{ + return readl(&(regs)->outbound_scratch_pad); +} + +/** + * megasas_clear_interrupt_ppc - Check & clear interrupt + * @regs: MFI register set + */ +static int +megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs) +{ + u32 status; + /* + * Check if it is our interrupt + */ + status = readl(®s->outbound_intr_status); + + if (!(status & MFI_REPLY_1078_MESSAGE_INTERRUPT)) { + return 0; + } + + /* + * Clear the interrupt by writing back the same value + */ + writel(status, ®s->outbound_doorbell_clear); + + /* Dummy readl to force pci flush */ + readl(®s->outbound_doorbell_clear); + + return 1; +} +/** + * megasas_fire_cmd_ppc - Sends command to the FW + * @frame_phys_addr : Physical address of cmd + * @frame_count : Number of frames for the command + * @regs : MFI register set + */ +static inline void +megasas_fire_cmd_ppc(struct megasas_instance *instance, + dma_addr_t frame_phys_addr, + u32 frame_count, + struct megasas_register_set __iomem *regs) +{ + unsigned long flags; + spin_lock_irqsave(&instance->hba_lock, flags); + writel((frame_phys_addr | (frame_count<<1))|1, + &(regs)->inbound_queue_port); + spin_unlock_irqrestore(&instance->hba_lock, flags); +} + +/** + * megasas_adp_reset_ppc - For controller reset + * @regs: MFI register set + */ +static int +megasas_adp_reset_ppc(struct megasas_instance *instance, + struct megasas_register_set __iomem *regs) +{ + return 0; +} + +/** + * megasas_check_reset_ppc - For controller reset check + * @regs: MFI register set + */ +static int +megasas_check_reset_ppc(struct megasas_instance *instance, + struct megasas_register_set __iomem *regs) +{ + return 0; +} +static struct megasas_instance_template megasas_instance_template_ppc = { + + .fire_cmd = megasas_fire_cmd_ppc, + .enable_intr = megasas_enable_intr_ppc, + .disable_intr = megasas_disable_intr_ppc, + .clear_intr = megasas_clear_intr_ppc, + .read_fw_status_reg = megasas_read_fw_status_reg_ppc, + .adp_reset = megasas_adp_reset_ppc, + .check_reset = megasas_check_reset_ppc, +}; + +/** + * megasas_enable_intr_skinny - Enables interrupts + * @regs: MFI register set + */ +static inline void +megasas_enable_intr_skinny(struct megasas_register_set __iomem *regs) +{ + writel(0xFFFFFFFF, &(regs)->outbound_intr_mask); + + writel(~MFI_SKINNY_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask); + + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_mask); +} + +/** + * megasas_disable_intr_skinny - Disables interrupt + * @regs: MFI register set + */ +static inline void +megasas_disable_intr_skinny(struct megasas_register_set __iomem *regs) +{ + u32 mask = 0xFFFFFFFF; + writel(mask, ®s->outbound_intr_mask); + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_mask); +} + +/** + * megasas_read_fw_status_reg_skinny - returns the current FW status value + * @regs: MFI register set + */ +static u32 +megasas_read_fw_status_reg_skinny(struct megasas_register_set __iomem *regs) +{ + return readl(&(regs)->outbound_scratch_pad); +} + +/** + * megasas_clear_interrupt_skinny - Check & clear interrupt + * @regs: MFI register set + */ +static int +megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs) +{ + u32 status; + /* + * Check if it is our interrupt + */ + status = readl(®s->outbound_intr_status); + + if (!(status & MFI_SKINNY_ENABLE_INTERRUPT_MASK)) { + return 0; + } + + /* + * Clear the interrupt by writing back the same value + */ + writel(status, ®s->outbound_intr_status); + + /* + * dummy read to flush PCI + */ + readl(®s->outbound_intr_status); + + return 1; +} + +/** + * megasas_fire_cmd_skinny - Sends command to the FW + * @frame_phys_addr : Physical address of cmd + * @frame_count : Number of frames for the command + * @regs : MFI register set + */ +static inline void +megasas_fire_cmd_skinny(struct megasas_instance *instance, + dma_addr_t frame_phys_addr, + u32 frame_count, + struct megasas_register_set __iomem *regs) +{ + unsigned long flags; + spin_lock_irqsave(&instance->hba_lock, flags); + writel(0, &(regs)->inbound_high_queue_port); + writel((frame_phys_addr | (frame_count<<1))|1, + &(regs)->inbound_low_queue_port); + spin_unlock_irqrestore(&instance->hba_lock, flags); +} + +/** + * megasas_adp_reset_skinny - For controller reset + * @regs: MFI register set + */ +static int +megasas_adp_reset_skinny(struct megasas_instance *instance, + struct megasas_register_set __iomem *regs) +{ + return 0; +} + +/** + * megasas_check_reset_skinny - For controller reset check + * @regs: MFI register set + */ +static int +megasas_check_reset_skinny(struct megasas_instance *instance, + struct megasas_register_set __iomem *regs) +{ + return 0; +} + +static struct megasas_instance_template megasas_instance_template_skinny = { + + .fire_cmd = megasas_fire_cmd_skinny, + .enable_intr = megasas_enable_intr_skinny, + .disable_intr = megasas_disable_intr_skinny, + .clear_intr = megasas_clear_intr_skinny, + .read_fw_status_reg = megasas_read_fw_status_reg_skinny, + .adp_reset = megasas_adp_reset_skinny, + .check_reset = megasas_check_reset_skinny, +}; + + +/** +* The following functions are defined for gen2 (deviceid : 0x78 0x79) +* controllers +*/ + +/** + * megasas_enable_intr_gen2 - Enables interrupts + * @regs: MFI register set + */ +static inline void +megasas_enable_intr_gen2(struct megasas_register_set __iomem *regs) +{ + writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear); + + /* write ~0x00000005 (4 & 1) to the intr mask*/ + writel(~MFI_GEN2_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask); + + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_mask); +} + +/** + * megasas_disable_intr_gen2 - Disables interrupt + * @regs: MFI register set + */ +static inline void +megasas_disable_intr_gen2(struct megasas_register_set __iomem *regs) +{ + u32 mask = 0xFFFFFFFF; + writel(mask, ®s->outbound_intr_mask); + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_mask); +} + +/** + * megasas_read_fw_status_reg_gen2 - returns the current FW status value + * @regs: MFI register set + */ +static u32 +megasas_read_fw_status_reg_gen2(struct megasas_register_set __iomem *regs) +{ + return readl(&(regs)->outbound_scratch_pad); +} + +/** + * megasas_clear_interrupt_gen2 - Check & clear interrupt + * @regs: MFI register set + */ +static int +megasas_clear_intr_gen2(struct megasas_register_set __iomem *regs) +{ + u32 status; + u32 mfiStatus = 0; + /* + * Check if it is our interrupt + */ + status = readl(®s->outbound_intr_status); + + if (status & MFI_GEN2_ENABLE_INTERRUPT_MASK) { + mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE; + } + if (status & MFI_G2_OUTBOUND_DOORBELL_CHANGE_INTERRUPT) { + mfiStatus |= MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE; + } + + /* + * Clear the interrupt by writing back the same value + */ + if (mfiStatus) + writel(status, ®s->outbound_doorbell_clear); + + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_status); + + return mfiStatus; +} +/** + * megasas_fire_cmd_gen2 - Sends command to the FW + * @frame_phys_addr : Physical address of cmd + * @frame_count : Number of frames for the command + * @regs : MFI register set + */ +static inline void +megasas_fire_cmd_gen2(struct megasas_instance *instance, + dma_addr_t frame_phys_addr, + u32 frame_count, + struct megasas_register_set __iomem *regs) +{ + unsigned long flags; + spin_lock_irqsave(&instance->hba_lock, flags); + writel((frame_phys_addr | (frame_count<<1))|1, + &(regs)->inbound_queue_port); + spin_unlock_irqrestore(&instance->hba_lock, flags); +} + +/** + * megasas_adp_reset_gen2 - For controller reset + * @regs: MFI register set + */ +static int +megasas_adp_reset_gen2(struct megasas_instance *instance, + struct megasas_register_set __iomem *reg_set) +{ + u32 retry = 0 ; + u32 HostDiag; + + writel(0, ®_set->seq_offset); + writel(4, ®_set->seq_offset); + writel(0xb, ®_set->seq_offset); + writel(2, ®_set->seq_offset); + writel(7, ®_set->seq_offset); + writel(0xd, ®_set->seq_offset); + msleep(1000); + + HostDiag = (u32)readl(®_set->host_diag); + + while ( !( HostDiag & DIAG_WRITE_ENABLE) ) { + msleep(100); + HostDiag = (u32)readl(®_set->host_diag); + printk(KERN_NOTICE "RESETGEN2: retry=%x, hostdiag=%x\n", + retry, HostDiag); + + if (retry++ >= 100) + return 1; + + } + + printk(KERN_NOTICE "ADP_RESET_GEN2: HostDiag=%x\n", HostDiag); + + writel((HostDiag | DIAG_RESET_ADAPTER), ®_set->host_diag); + + ssleep(10); + + HostDiag = (u32)readl(®_set->host_diag); + while ( ( HostDiag & DIAG_RESET_ADAPTER) ) { + msleep(100); + HostDiag = (u32)readl(®_set->host_diag); + printk(KERN_NOTICE "RESET_GEN2: retry=%x, hostdiag=%x\n", + retry, HostDiag); + + if (retry++ >= 1000) + return 1; + + } + return 0; +} + +/** + * megasas_check_reset_gen2 - For controller reset check + * @regs: MFI register set + */ +static int +megasas_check_reset_gen2(struct megasas_instance *instance, + struct megasas_register_set __iomem *regs) +{ + if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) { + return 1; + } + + return 0; +} + +static struct megasas_instance_template megasas_instance_template_gen2 = { + + .fire_cmd = megasas_fire_cmd_gen2, + .enable_intr = megasas_enable_intr_gen2, + .disable_intr = megasas_disable_intr_gen2, + .clear_intr = megasas_clear_intr_gen2, + .read_fw_status_reg = megasas_read_fw_status_reg_gen2, + .adp_reset = megasas_adp_reset_gen2, + .check_reset = megasas_check_reset_gen2, +}; + +/** +* This is the end of set of functions & definitions +* specific to gen2 (deviceid : 0x78, 0x79) controllers +*/ + +/** + * megasas_issue_polled - Issues a polling command + * @instance: Adapter soft state + * @cmd: Command packet to be issued + * + * For polling, MFI requires the cmd_status to be set to 0xFF before posting. + */ +static int +megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd) +{ + int i; + u32 msecs = MFI_POLL_TIMEOUT_SECS * 1000; + + struct megasas_header *frame_hdr = &cmd->frame->hdr; + + frame_hdr->cmd_status = 0xFF; + frame_hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE; + + /* + * Issue the frame using inbound queue port + */ + instance->instancet->fire_cmd(instance, + cmd->frame_phys_addr, 0, instance->reg_set); + + /* + * Wait for cmd_status to change + */ + for (i = 0; (i < msecs) && (frame_hdr->cmd_status == 0xff); i++) { + rmb(); + msleep(1); + } + + if (frame_hdr->cmd_status == 0xff) + return -ETIME; + + return 0; +} + +/** + * megasas_issue_blocked_cmd - Synchronous wrapper around regular FW cmds + * @instance: Adapter soft state + * @cmd: Command to be issued + * + * This function waits on an event for the command to be returned from ISR. + * Max wait time is MEGASAS_INTERNAL_CMD_WAIT_TIME secs + * Used to issue ioctl commands. + */ +static int +megasas_issue_blocked_cmd(struct megasas_instance *instance, + struct megasas_cmd *cmd) +{ + cmd->cmd_status = ENODATA; + + instance->instancet->fire_cmd(instance, + cmd->frame_phys_addr, 0, instance->reg_set); + + wait_event(instance->int_cmd_wait_q, cmd->cmd_status != ENODATA); + + return 0; +} + +/** + * megasas_issue_blocked_abort_cmd - Aborts previously issued cmd + * @instance: Adapter soft state + * @cmd_to_abort: Previously issued cmd to be aborted + * + * MFI firmware can abort previously issued AEN comamnd (automatic event + * notification). The megasas_issue_blocked_abort_cmd() issues such abort + * cmd and waits for return status. + * Max wait time is MEGASAS_INTERNAL_CMD_WAIT_TIME secs + */ +static int +megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, + struct megasas_cmd *cmd_to_abort) +{ + struct megasas_cmd *cmd; + struct megasas_abort_frame *abort_fr; + + cmd = megasas_get_cmd(instance); + + if (!cmd) + return -1; + + abort_fr = &cmd->frame->abort; + + /* + * Prepare and issue the abort frame + */ + abort_fr->cmd = MFI_CMD_ABORT; + abort_fr->cmd_status = 0xFF; + abort_fr->flags = 0; + abort_fr->abort_context = cmd_to_abort->index; + abort_fr->abort_mfi_phys_addr_lo = cmd_to_abort->frame_phys_addr; + abort_fr->abort_mfi_phys_addr_hi = 0; + + cmd->sync_cmd = 1; + cmd->cmd_status = 0xFF; + + instance->instancet->fire_cmd(instance, + cmd->frame_phys_addr, 0, instance->reg_set); + + /* + * Wait for this cmd to complete + */ + wait_event(instance->abort_cmd_wait_q, cmd->cmd_status != 0xFF); + cmd->sync_cmd = 0; + + megasas_return_cmd(instance, cmd); + return 0; +} + +/** + * megasas_make_sgl32 - Prepares 32-bit SGL + * @instance: Adapter soft state + * @scp: SCSI command from the mid-layer + * @mfi_sgl: SGL to be filled in + * + * If successful, this function returns the number of SG elements. Otherwise, + * it returnes -1. + */ +static int +megasas_make_sgl32(struct megasas_instance *instance, struct scsi_cmnd *scp, + union megasas_sgl *mfi_sgl) +{ + int i; + int sge_count; + struct scatterlist *os_sgl; + + sge_count = scsi_dma_map(scp); + BUG_ON(sge_count < 0); + + if (sge_count) { + scsi_for_each_sg(scp, os_sgl, sge_count, i) { + mfi_sgl->sge32[i].length = sg_dma_len(os_sgl); + mfi_sgl->sge32[i].phys_addr = sg_dma_address(os_sgl); + } + } + return sge_count; +} + +/** + * megasas_make_sgl64 - Prepares 64-bit SGL + * @instance: Adapter soft state + * @scp: SCSI command from the mid-layer + * @mfi_sgl: SGL to be filled in + * + * If successful, this function returns the number of SG elements. Otherwise, + * it returnes -1. + */ +static int +megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, + union megasas_sgl *mfi_sgl) +{ + int i; + int sge_count; + struct scatterlist *os_sgl; + + sge_count = scsi_dma_map(scp); + BUG_ON(sge_count < 0); + + if (sge_count) { + scsi_for_each_sg(scp, os_sgl, sge_count, i) { + mfi_sgl->sge64[i].length = sg_dma_len(os_sgl); + mfi_sgl->sge64[i].phys_addr = sg_dma_address(os_sgl); + } + } + return sge_count; +} + +/** + * megasas_make_sgl_skinny - Prepares IEEE SGL + * @instance: Adapter soft state + * @scp: SCSI command from the mid-layer + * @mfi_sgl: SGL to be filled in + * + * If successful, this function returns the number of SG elements. Otherwise, + * it returnes -1. + */ +static int +megasas_make_sgl_skinny(struct megasas_instance *instance, + struct scsi_cmnd *scp, union megasas_sgl *mfi_sgl) +{ + int i; + int sge_count; + struct scatterlist *os_sgl; + + sge_count = scsi_dma_map(scp); + + if (sge_count) { + scsi_for_each_sg(scp, os_sgl, sge_count, i) { + mfi_sgl->sge_skinny[i].length = sg_dma_len(os_sgl); + mfi_sgl->sge_skinny[i].phys_addr = + sg_dma_address(os_sgl); + mfi_sgl->sge_skinny[i].flag = 0; + } + } + return sge_count; +} + + /** + * megasas_get_frame_count - Computes the number of frames + * @frame_type : type of frame- io or pthru frame + * @sge_count : number of sg elements + * + * Returns the number of frames required for numnber of sge's (sge_count) + */ + +static u32 megasas_get_frame_count(struct megasas_instance *instance, + u8 sge_count, u8 frame_type) +{ + int num_cnt; + int sge_bytes; + u32 sge_sz; + u32 frame_count=0; + + sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : + sizeof(struct megasas_sge32); + + if (instance->flag_ieee) { + sge_sz = sizeof(struct megasas_sge_skinny); + } + + /* + * Main frame can contain 2 SGEs for 64-bit SGLs and + * 3 SGEs for 32-bit SGLs for ldio & + * 1 SGEs for 64-bit SGLs and + * 2 SGEs for 32-bit SGLs for pthru frame + */ + if (unlikely(frame_type == PTHRU_FRAME)) { + if (instance->flag_ieee == 1) { + num_cnt = sge_count - 1; + } else if (IS_DMA64) + num_cnt = sge_count - 1; + else + num_cnt = sge_count - 2; + } else { + if (instance->flag_ieee == 1) { + num_cnt = sge_count - 1; + } else if (IS_DMA64) + num_cnt = sge_count - 2; + else + num_cnt = sge_count - 3; + } + + if(num_cnt>0){ + sge_bytes = sge_sz * num_cnt; + + frame_count = (sge_bytes / MEGAMFI_FRAME_SIZE) + + ((sge_bytes % MEGAMFI_FRAME_SIZE) ? 1 : 0) ; + } + /* Main frame */ + frame_count +=1; + + if (frame_count > 7) + frame_count = 8; + return frame_count; +} + +/** + * megasas_build_dcdb - Prepares a direct cdb (DCDB) command + * @instance: Adapter soft state + * @scp: SCSI command + * @cmd: Command to be prepared in + * + * This function prepares CDB commands. These are typcially pass-through + * commands to the devices. + */ +static int +megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, + struct megasas_cmd *cmd) +{ + u32 is_logical; + u32 device_id; + u16 flags = 0; + struct megasas_pthru_frame *pthru; + + is_logical = MEGASAS_IS_LOGICAL(scp); + device_id = MEGASAS_DEV_INDEX(instance, scp); + pthru = (struct megasas_pthru_frame *)cmd->frame; + + if (scp->sc_data_direction == PCI_DMA_TODEVICE) + flags = MFI_FRAME_DIR_WRITE; + else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) + flags = MFI_FRAME_DIR_READ; + else if (scp->sc_data_direction == PCI_DMA_NONE) + flags = MFI_FRAME_DIR_NONE; + + if (instance->flag_ieee == 1) { + flags |= MFI_FRAME_IEEE; + } + + /* + * Prepare the DCDB frame + */ + pthru->cmd = (is_logical) ? MFI_CMD_LD_SCSI_IO : MFI_CMD_PD_SCSI_IO; + pthru->cmd_status = 0x0; + pthru->scsi_status = 0x0; + pthru->target_id = device_id; + pthru->lun = scp->device->lun; + pthru->cdb_len = scp->cmd_len; + pthru->timeout = 0; + pthru->pad_0 = 0; + pthru->flags = flags; + pthru->data_xfer_len = scsi_bufflen(scp); + + memcpy(pthru->cdb, scp->cmnd, scp->cmd_len); + + /* + * If the command is for the tape device, set the + * pthru timeout to the os layer timeout value. + */ + if (scp->device->type == TYPE_TAPE) { + if ((scp->request->timeout / HZ) > 0xFFFF) + pthru->timeout = 0xFFFF; + else + pthru->timeout = scp->request->timeout / HZ; + } + + /* + * Construct SGL + */ + if (instance->flag_ieee == 1) { + pthru->flags |= MFI_FRAME_SGL64; + pthru->sge_count = megasas_make_sgl_skinny(instance, scp, + &pthru->sgl); + } else if (IS_DMA64) { + pthru->flags |= MFI_FRAME_SGL64; + pthru->sge_count = megasas_make_sgl64(instance, scp, + &pthru->sgl); + } else + pthru->sge_count = megasas_make_sgl32(instance, scp, + &pthru->sgl); + + if (pthru->sge_count > instance->max_num_sge) { + printk(KERN_ERR "megasas: DCDB two many SGE NUM=%x\n", + pthru->sge_count); + return 0; + } + + /* + * Sense info specific + */ + pthru->sense_len = SCSI_SENSE_BUFFERSIZE; + pthru->sense_buf_phys_addr_hi = 0; + pthru->sense_buf_phys_addr_lo = cmd->sense_phys_addr; + + /* + * Compute the total number of frames this command consumes. FW uses + * this number to pull sufficient number of frames from host memory. + */ + cmd->frame_count = megasas_get_frame_count(instance, pthru->sge_count, + PTHRU_FRAME); + + return cmd->frame_count; +} + +/** + * megasas_build_ldio - Prepares IOs to logical devices + * @instance: Adapter soft state + * @scp: SCSI command + * @cmd: Command to be prepared + * + * Frames (and accompanying SGLs) for regular SCSI IOs use this function. + */ +static int +megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, + struct megasas_cmd *cmd) +{ + u32 device_id; + u8 sc = scp->cmnd[0]; + u16 flags = 0; + struct megasas_io_frame *ldio; + + device_id = MEGASAS_DEV_INDEX(instance, scp); + ldio = (struct megasas_io_frame *)cmd->frame; + + if (scp->sc_data_direction == PCI_DMA_TODEVICE) + flags = MFI_FRAME_DIR_WRITE; + else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) + flags = MFI_FRAME_DIR_READ; + + if (instance->flag_ieee == 1) { + flags |= MFI_FRAME_IEEE; + } + + /* + * Prepare the Logical IO frame: 2nd bit is zero for all read cmds + */ + ldio->cmd = (sc & 0x02) ? MFI_CMD_LD_WRITE : MFI_CMD_LD_READ; + ldio->cmd_status = 0x0; + ldio->scsi_status = 0x0; + ldio->target_id = device_id; + ldio->timeout = 0; + ldio->reserved_0 = 0; + ldio->pad_0 = 0; + ldio->flags = flags; + ldio->start_lba_hi = 0; + ldio->access_byte = (scp->cmd_len != 6) ? scp->cmnd[1] : 0; + + /* + * 6-byte READ(0x08) or WRITE(0x0A) cdb + */ + if (scp->cmd_len == 6) { + ldio->lba_count = (u32) scp->cmnd[4]; + ldio->start_lba_lo = ((u32) scp->cmnd[1] << 16) | + ((u32) scp->cmnd[2] << 8) | (u32) scp->cmnd[3]; + + ldio->start_lba_lo &= 0x1FFFFF; + } + + /* + * 10-byte READ(0x28) or WRITE(0x2A) cdb + */ + else if (scp->cmd_len == 10) { + ldio->lba_count = (u32) scp->cmnd[8] | + ((u32) scp->cmnd[7] << 8); + ldio->start_lba_lo = ((u32) scp->cmnd[2] << 24) | + ((u32) scp->cmnd[3] << 16) | + ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5]; + } + + /* + * 12-byte READ(0xA8) or WRITE(0xAA) cdb + */ + else if (scp->cmd_len == 12) { + ldio->lba_count = ((u32) scp->cmnd[6] << 24) | + ((u32) scp->cmnd[7] << 16) | + ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9]; + + ldio->start_lba_lo = ((u32) scp->cmnd[2] << 24) | + ((u32) scp->cmnd[3] << 16) | + ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5]; + } + + /* + * 16-byte READ(0x88) or WRITE(0x8A) cdb + */ + else if (scp->cmd_len == 16) { + ldio->lba_count = ((u32) scp->cmnd[10] << 24) | + ((u32) scp->cmnd[11] << 16) | + ((u32) scp->cmnd[12] << 8) | (u32) scp->cmnd[13]; + + ldio->start_lba_lo = ((u32) scp->cmnd[6] << 24) | + ((u32) scp->cmnd[7] << 16) | + ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9]; + + ldio->start_lba_hi = ((u32) scp->cmnd[2] << 24) | + ((u32) scp->cmnd[3] << 16) | + ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5]; + + } + + /* + * Construct SGL + */ + if (instance->flag_ieee) { + ldio->flags |= MFI_FRAME_SGL64; + ldio->sge_count = megasas_make_sgl_skinny(instance, scp, + &ldio->sgl); + } else if (IS_DMA64) { + ldio->flags |= MFI_FRAME_SGL64; + ldio->sge_count = megasas_make_sgl64(instance, scp, &ldio->sgl); + } else + ldio->sge_count = megasas_make_sgl32(instance, scp, &ldio->sgl); + + if (ldio->sge_count > instance->max_num_sge) { + printk(KERN_ERR "megasas: build_ld_io: sge_count = %x\n", + ldio->sge_count); + return 0; + } + + /* + * Sense info specific + */ + ldio->sense_len = SCSI_SENSE_BUFFERSIZE; + ldio->sense_buf_phys_addr_hi = 0; + ldio->sense_buf_phys_addr_lo = cmd->sense_phys_addr; + + /* + * Compute the total number of frames this command consumes. FW uses + * this number to pull sufficient number of frames from host memory. + */ + cmd->frame_count = megasas_get_frame_count(instance, + ldio->sge_count, IO_FRAME); + + return cmd->frame_count; +} + +/** + * megasas_is_ldio - Checks if the cmd is for logical drive + * @scmd: SCSI command + * + * Called by megasas_queue_command to find out if the command to be queued + * is a logical drive command + */ +static inline int megasas_is_ldio(struct scsi_cmnd *cmd) +{ + if (!MEGASAS_IS_LOGICAL(cmd)) + return 0; + switch (cmd->cmnd[0]) { + case READ_10: + case WRITE_10: + case READ_12: + case WRITE_12: + case READ_6: + case WRITE_6: + case READ_16: + case WRITE_16: + return 1; + default: + return 0; + } +} + + /** + * megasas_dump_pending_frames - Dumps the frame address of all pending cmds + * in FW + * @instance: Adapter soft state + */ +static inline void +megasas_dump_pending_frames(struct megasas_instance *instance) +{ + struct megasas_cmd *cmd; + int i,n; + union megasas_sgl *mfi_sgl; + struct megasas_io_frame *ldio; + struct megasas_pthru_frame *pthru; + u32 sgcount; + u32 max_cmd = instance->max_fw_cmds; + + printk(KERN_ERR "\nmegasas[%d]: Dumping Frame Phys Address of all pending cmds in FW\n",instance->host->host_no); + printk(KERN_ERR "megasas[%d]: Total OS Pending cmds : %d\n",instance->host->host_no,atomic_read(&instance->fw_outstanding)); + if (IS_DMA64) + printk(KERN_ERR "\nmegasas[%d]: 64 bit SGLs were sent to FW\n",instance->host->host_no); + else + printk(KERN_ERR "\nmegasas[%d]: 32 bit SGLs were sent to FW\n",instance->host->host_no); + + printk(KERN_ERR "megasas[%d]: Pending OS cmds in FW : \n",instance->host->host_no); + for (i = 0; i < max_cmd; i++) { + cmd = instance->cmd_list[i]; + if(!cmd->scmd) + continue; + printk(KERN_ERR "megasas[%d]: Frame addr :0x%08lx : ",instance->host->host_no,(unsigned long)cmd->frame_phys_addr); + if (megasas_is_ldio(cmd->scmd)){ + ldio = (struct megasas_io_frame *)cmd->frame; + mfi_sgl = &ldio->sgl; + sgcount = ldio->sge_count; + printk(KERN_ERR "megasas[%d]: frame count : 0x%x, Cmd : 0x%x, Tgt id : 0x%x, lba lo : 0x%x, lba_hi : 0x%x, sense_buf addr : 0x%x,sge count : 0x%x\n",instance->host->host_no, cmd->frame_count,ldio->cmd,ldio->target_id, ldio->start_lba_lo,ldio->start_lba_hi,ldio->sense_buf_phys_addr_lo,sgcount); + } + else { + pthru = (struct megasas_pthru_frame *) cmd->frame; + mfi_sgl = &pthru->sgl; + sgcount = pthru->sge_count; + printk(KERN_ERR "megasas[%d]: frame count : 0x%x, Cmd : 0x%x, Tgt id : 0x%x, lun : 0x%x, cdb_len : 0x%x, data xfer len : 0x%x, sense_buf addr : 0x%x,sge count : 0x%x\n",instance->host->host_no,cmd->frame_count,pthru->cmd,pthru->target_id,pthru->lun,pthru->cdb_len , pthru->data_xfer_len,pthru->sense_buf_phys_addr_lo,sgcount); + } + if(megasas_dbg_lvl & MEGASAS_DBG_LVL){ + for (n = 0; n < sgcount; n++){ + if (IS_DMA64) + printk(KERN_ERR "megasas: sgl len : 0x%x, sgl addr : 0x%08lx ",mfi_sgl->sge64[n].length , (unsigned long)mfi_sgl->sge64[n].phys_addr) ; + else + printk(KERN_ERR "megasas: sgl len : 0x%x, sgl addr : 0x%x ",mfi_sgl->sge32[n].length , mfi_sgl->sge32[n].phys_addr) ; + } + } + printk(KERN_ERR "\n"); + } /*for max_cmd*/ + printk(KERN_ERR "\nmegasas[%d]: Pending Internal cmds in FW : \n",instance->host->host_no); + for (i = 0; i < max_cmd; i++) { + + cmd = instance->cmd_list[i]; + + if(cmd->sync_cmd == 1){ + printk(KERN_ERR "0x%08lx : ", (unsigned long)cmd->frame_phys_addr); + } + } + printk(KERN_ERR "megasas[%d]: Dumping Done.\n\n",instance->host->host_no); +} + +/** + * megasas_queue_command - Queue entry point + * @scmd: SCSI command to be queued + * @done: Callback entry point + */ +static int +megasas_queue_command_lck(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *)) +{ + u32 frame_count; + struct megasas_cmd *cmd; + struct megasas_instance *instance; + unsigned long flags; + + instance = (struct megasas_instance *) + scmd->device->host->hostdata; + + if (instance->issuepend_done == 0) + return SCSI_MLQUEUE_HOST_BUSY; + + spin_lock_irqsave(&instance->hba_lock, flags); + if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) { + spin_unlock_irqrestore(&instance->hba_lock, flags); + return SCSI_MLQUEUE_HOST_BUSY; + } + + spin_unlock_irqrestore(&instance->hba_lock, flags); + + scmd->scsi_done = done; + scmd->result = 0; + + if (MEGASAS_IS_LOGICAL(scmd) && + (scmd->device->id >= MEGASAS_MAX_LD || scmd->device->lun)) { + scmd->result = DID_BAD_TARGET << 16; + goto out_done; + } + + switch (scmd->cmnd[0]) { + case SYNCHRONIZE_CACHE: + /* + * FW takes care of flush cache on its own + * No need to send it down + */ + scmd->result = DID_OK << 16; + goto out_done; + default: + break; + } + + cmd = megasas_get_cmd(instance); + if (!cmd) + return SCSI_MLQUEUE_HOST_BUSY; + + /* + * Logical drive command + */ + if (megasas_is_ldio(scmd)) + frame_count = megasas_build_ldio(instance, scmd, cmd); + else + frame_count = megasas_build_dcdb(instance, scmd, cmd); + + if (!frame_count) + goto out_return_cmd; + + cmd->scmd = scmd; + scmd->SCp.ptr = (char *)cmd; + + /* + * Issue the command to the FW + */ + atomic_inc(&instance->fw_outstanding); + + instance->instancet->fire_cmd(instance, cmd->frame_phys_addr, + cmd->frame_count-1, instance->reg_set); + /* + * Check if we have pend cmds to be completed + */ + if (poll_mode_io && atomic_read(&instance->fw_outstanding)) + tasklet_schedule(&instance->isr_tasklet); + + + return 0; + + out_return_cmd: + megasas_return_cmd(instance, cmd); + out_done: + done(scmd); + return 0; +} + +static DEF_SCSI_QCMD(megasas_queue_command) + +static struct megasas_instance *megasas_lookup_instance(u16 host_no) +{ + int i; + + for (i = 0; i < megasas_mgmt_info.max_index; i++) { + + if ((megasas_mgmt_info.instance[i]) && + (megasas_mgmt_info.instance[i]->host->host_no == host_no)) + return megasas_mgmt_info.instance[i]; + } + + return NULL; +} + +static int megasas_slave_configure(struct scsi_device *sdev) +{ + u16 pd_index = 0; + struct megasas_instance *instance ; + + instance = megasas_lookup_instance(sdev->host->host_no); + + /* + * Don't export physical disk devices to the disk driver. + * + * FIXME: Currently we don't export them to the midlayer at all. + * That will be fixed once LSI engineers have audited the + * firmware for possible issues. + */ + if (sdev->channel < MEGASAS_MAX_PD_CHANNELS && + sdev->type == TYPE_DISK) { + pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + + sdev->id; + if (instance->pd_list[pd_index].driveState == + MR_PD_STATE_SYSTEM) { + blk_queue_rq_timeout(sdev->request_queue, + MEGASAS_DEFAULT_CMD_TIMEOUT * HZ); + return 0; + } + return -ENXIO; + } + + /* + * The RAID firmware may require extended timeouts. + */ + blk_queue_rq_timeout(sdev->request_queue, + MEGASAS_DEFAULT_CMD_TIMEOUT * HZ); + return 0; +} + +static int megasas_slave_alloc(struct scsi_device *sdev) +{ + u16 pd_index = 0; + struct megasas_instance *instance ; + instance = megasas_lookup_instance(sdev->host->host_no); + if ((sdev->channel < MEGASAS_MAX_PD_CHANNELS) && + (sdev->type == TYPE_DISK)) { + /* + * Open the OS scan to the SYSTEM PD + */ + pd_index = + (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + + sdev->id; + if ((instance->pd_list[pd_index].driveState == + MR_PD_STATE_SYSTEM) && + (instance->pd_list[pd_index].driveType == + TYPE_DISK)) { + return 0; + } + return -ENXIO; + } + return 0; +} + +static void megaraid_sas_kill_hba(struct megasas_instance *instance) +{ + if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || + (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { + writel(MFI_STOP_ADP, + &instance->reg_set->reserved_0[0]); + } else { + writel(MFI_STOP_ADP, + &instance->reg_set->inbound_doorbell); + } +} + +/** + * megasas_complete_cmd_dpc - Returns FW's controller structure + * @instance_addr: Address of adapter soft state + * + * Tasklet to complete cmds + */ +static void megasas_complete_cmd_dpc(unsigned long instance_addr) +{ + u32 producer; + u32 consumer; + u32 context; + struct megasas_cmd *cmd; + struct megasas_instance *instance = + (struct megasas_instance *)instance_addr; + unsigned long flags; + + /* If we have already declared adapter dead, donot complete cmds */ + if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR ) + return; + + spin_lock_irqsave(&instance->completion_lock, flags); + + producer = *instance->producer; + consumer = *instance->consumer; + + while (consumer != producer) { + context = instance->reply_queue[consumer]; + if (context >= instance->max_fw_cmds) { + printk(KERN_ERR "Unexpected context value %x\n", + context); + BUG(); + } + + cmd = instance->cmd_list[context]; + + megasas_complete_cmd(instance, cmd, DID_OK); + + consumer++; + if (consumer == (instance->max_fw_cmds + 1)) { + consumer = 0; + } + } + + *instance->consumer = producer; + + spin_unlock_irqrestore(&instance->completion_lock, flags); + + /* + * Check if we can restore can_queue + */ + if (instance->flag & MEGASAS_FW_BUSY + && time_after(jiffies, instance->last_time + 5 * HZ) + && atomic_read(&instance->fw_outstanding) < 17) { + + spin_lock_irqsave(instance->host->host_lock, flags); + instance->flag &= ~MEGASAS_FW_BUSY; + if ((instance->pdev->device == + PCI_DEVICE_ID_LSI_SAS0073SKINNY) || + (instance->pdev->device == + PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { + instance->host->can_queue = + instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS; + } else + instance->host->can_queue = + instance->max_fw_cmds - MEGASAS_INT_CMDS; + + spin_unlock_irqrestore(instance->host->host_lock, flags); + } +} + +static void +megasas_internal_reset_defer_cmds(struct megasas_instance *instance); + +static void +process_fw_state_change_wq(struct work_struct *work); + +void megasas_do_ocr(struct megasas_instance *instance) +{ + if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1064R) || + (instance->pdev->device == PCI_DEVICE_ID_DELL_PERC5) || + (instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR)) { + *instance->consumer = MEGASAS_ADPRESET_INPROG_SIGN; + } + instance->instancet->disable_intr(instance->reg_set); + instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT; + instance->issuepend_done = 0; + + atomic_set(&instance->fw_outstanding, 0); + megasas_internal_reset_defer_cmds(instance); + process_fw_state_change_wq(&instance->work_init); +} + +/** + * megasas_wait_for_outstanding - Wait for all outstanding cmds + * @instance: Adapter soft state + * + * This function waits for upto MEGASAS_RESET_WAIT_TIME seconds for FW to + * complete all its outstanding commands. Returns error if one or more IOs + * are pending after this time period. It also marks the controller dead. + */ +static int megasas_wait_for_outstanding(struct megasas_instance *instance) +{ + int i; + u32 reset_index; + u32 wait_time = MEGASAS_RESET_WAIT_TIME; + u8 adprecovery; + unsigned long flags; + struct list_head clist_local; + struct megasas_cmd *reset_cmd; + u32 fw_state; + u8 kill_adapter_flag; + + spin_lock_irqsave(&instance->hba_lock, flags); + adprecovery = instance->adprecovery; + spin_unlock_irqrestore(&instance->hba_lock, flags); + + if (adprecovery != MEGASAS_HBA_OPERATIONAL) { + + INIT_LIST_HEAD(&clist_local); + spin_lock_irqsave(&instance->hba_lock, flags); + list_splice_init(&instance->internal_reset_pending_q, + &clist_local); + spin_unlock_irqrestore(&instance->hba_lock, flags); + + printk(KERN_NOTICE "megasas: HBA reset wait ...\n"); + for (i = 0; i < wait_time; i++) { + msleep(1000); + spin_lock_irqsave(&instance->hba_lock, flags); + adprecovery = instance->adprecovery; + spin_unlock_irqrestore(&instance->hba_lock, flags); + if (adprecovery == MEGASAS_HBA_OPERATIONAL) + break; + } + + if (adprecovery != MEGASAS_HBA_OPERATIONAL) { + printk(KERN_NOTICE "megasas: reset: Stopping HBA.\n"); + spin_lock_irqsave(&instance->hba_lock, flags); + instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR; + spin_unlock_irqrestore(&instance->hba_lock, flags); + return FAILED; + } + + reset_index = 0; + while (!list_empty(&clist_local)) { + reset_cmd = list_entry((&clist_local)->next, + struct megasas_cmd, list); + list_del_init(&reset_cmd->list); + if (reset_cmd->scmd) { + reset_cmd->scmd->result = DID_RESET << 16; + printk(KERN_NOTICE "%d:%p reset [%02x], %#lx\n", + reset_index, reset_cmd, + reset_cmd->scmd->cmnd[0], + reset_cmd->scmd->serial_number); + + reset_cmd->scmd->scsi_done(reset_cmd->scmd); + megasas_return_cmd(instance, reset_cmd); + } else if (reset_cmd->sync_cmd) { + printk(KERN_NOTICE "megasas:%p synch cmds" + "reset queue\n", + reset_cmd); + + reset_cmd->cmd_status = ENODATA; + instance->instancet->fire_cmd(instance, + reset_cmd->frame_phys_addr, + 0, instance->reg_set); + } else { + printk(KERN_NOTICE "megasas: %p unexpected" + "cmds lst\n", + reset_cmd); + } + reset_index++; + } + + return SUCCESS; + } + + for (i = 0; i < wait_time; i++) { + + int outstanding = atomic_read(&instance->fw_outstanding); + + if (!outstanding) + break; + + if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { + printk(KERN_NOTICE "megasas: [%2d]waiting for %d " + "commands to complete\n",i,outstanding); + /* + * Call cmd completion routine. Cmd to be + * be completed directly without depending on isr. + */ + megasas_complete_cmd_dpc((unsigned long)instance); + } + + msleep(1000); + } + + i = 0; + kill_adapter_flag = 0; + do { + fw_state = instance->instancet->read_fw_status_reg( + instance->reg_set) & MFI_STATE_MASK; + if ((fw_state == MFI_STATE_FAULT) && + (instance->disableOnlineCtrlReset == 0)) { + if (i == 3) { + kill_adapter_flag = 2; + break; + } + megasas_do_ocr(instance); + kill_adapter_flag = 1; + + /* wait for 1 secs to let FW finish the pending cmds */ + msleep(1000); + } + i++; + } while (i <= 3); + + if (atomic_read(&instance->fw_outstanding) && + !kill_adapter_flag) { + if (instance->disableOnlineCtrlReset == 0) { + + megasas_do_ocr(instance); + + /* wait for 5 secs to let FW finish the pending cmds */ + for (i = 0; i < wait_time; i++) { + int outstanding = + atomic_read(&instance->fw_outstanding); + if (!outstanding) + return SUCCESS; + msleep(1000); + } + } + } + + if (atomic_read(&instance->fw_outstanding) || + (kill_adapter_flag == 2)) { + printk(KERN_NOTICE "megaraid_sas: pending cmds after reset\n"); + /* + * Send signal to FW to stop processing any pending cmds. + * The controller will be taken offline by the OS now. + */ + if ((instance->pdev->device == + PCI_DEVICE_ID_LSI_SAS0073SKINNY) || + (instance->pdev->device == + PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { + writel(MFI_STOP_ADP, + &instance->reg_set->reserved_0[0]); + } else { + writel(MFI_STOP_ADP, + &instance->reg_set->inbound_doorbell); + } + megasas_dump_pending_frames(instance); + spin_lock_irqsave(&instance->hba_lock, flags); + instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR; + spin_unlock_irqrestore(&instance->hba_lock, flags); + return FAILED; + } + + printk(KERN_NOTICE "megaraid_sas: no pending cmds after reset\n"); + + return SUCCESS; +} + +/** + * megasas_generic_reset - Generic reset routine + * @scmd: Mid-layer SCSI command + * + * This routine implements a generic reset handler for device, bus and host + * reset requests. Device, bus and host specific reset handlers can use this + * function after they do their specific tasks. + */ +static int megasas_generic_reset(struct scsi_cmnd *scmd) +{ + int ret_val; + struct megasas_instance *instance; + + instance = (struct megasas_instance *)scmd->device->host->hostdata; + + scmd_printk(KERN_NOTICE, scmd, "megasas: RESET -%ld cmd=%x retries=%x\n", + scmd->serial_number, scmd->cmnd[0], scmd->retries); + + if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) { + printk(KERN_ERR "megasas: cannot recover from previous reset " + "failures\n"); + return FAILED; + } + + ret_val = megasas_wait_for_outstanding(instance); + if (ret_val == SUCCESS) + printk(KERN_NOTICE "megasas: reset successful \n"); + else + printk(KERN_ERR "megasas: failed to do reset\n"); + + return ret_val; +} + +/** + * megasas_reset_timer - quiesce the adapter if required + * @scmd: scsi cmnd + * + * Sets the FW busy flag and reduces the host->can_queue if the + * cmd has not been completed within the timeout period. + */ +static enum +blk_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd) +{ + struct megasas_cmd *cmd = (struct megasas_cmd *)scmd->SCp.ptr; + struct megasas_instance *instance; + unsigned long flags; + + if (time_after(jiffies, scmd->jiffies_at_alloc + + (MEGASAS_DEFAULT_CMD_TIMEOUT * 2) * HZ)) { + return BLK_EH_NOT_HANDLED; + } + + instance = cmd->instance; + if (!(instance->flag & MEGASAS_FW_BUSY)) { + /* FW is busy, throttle IO */ + spin_lock_irqsave(instance->host->host_lock, flags); + + instance->host->can_queue = 16; + instance->last_time = jiffies; + instance->flag |= MEGASAS_FW_BUSY; + + spin_unlock_irqrestore(instance->host->host_lock, flags); + } + return BLK_EH_RESET_TIMER; +} + +/** + * megasas_reset_device - Device reset handler entry point + */ +static int megasas_reset_device(struct scsi_cmnd *scmd) +{ + int ret; + + /* + * First wait for all commands to complete + */ + ret = megasas_generic_reset(scmd); + + return ret; +} + +/** + * megasas_reset_bus_host - Bus & host reset handler entry point + */ +static int megasas_reset_bus_host(struct scsi_cmnd *scmd) +{ + int ret; + + /* + * First wait for all commands to complete + */ + ret = megasas_generic_reset(scmd); + + return ret; +} + +/** + * megasas_bios_param - Returns disk geometry for a disk + * @sdev: device handle + * @bdev: block device + * @capacity: drive capacity + * @geom: geometry parameters + */ +static int +megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev, + sector_t capacity, int geom[]) +{ + int heads; + int sectors; + sector_t cylinders; + unsigned long tmp; + /* Default heads (64) & sectors (32) */ + heads = 64; + sectors = 32; + + tmp = heads * sectors; + cylinders = capacity; + + sector_div(cylinders, tmp); + + /* + * Handle extended translation size for logical drives > 1Gb + */ + + if (capacity >= 0x200000) { + heads = 255; + sectors = 63; + tmp = heads*sectors; + cylinders = capacity; + sector_div(cylinders, tmp); + } + + geom[0] = heads; + geom[1] = sectors; + geom[2] = cylinders; + + return 0; +} + +static void megasas_aen_polling(struct work_struct *work); + +/** + * megasas_service_aen - Processes an event notification + * @instance: Adapter soft state + * @cmd: AEN command completed by the ISR + * + * For AEN, driver sends a command down to FW that is held by the FW till an + * event occurs. When an event of interest occurs, FW completes the command + * that it was previously holding. + * + * This routines sends SIGIO signal to processes that have registered with the + * driver for AEN. + */ +static void +megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd) +{ + unsigned long flags; + /* + * Don't signal app if it is just an aborted previously registered aen + */ + if ((!cmd->abort_aen) && (instance->unload == 0)) { + spin_lock_irqsave(&poll_aen_lock, flags); + megasas_poll_wait_aen = 1; + spin_unlock_irqrestore(&poll_aen_lock, flags); + wake_up(&megasas_poll_wait); + kill_fasync(&megasas_async_queue, SIGIO, POLL_IN); + } + else + cmd->abort_aen = 0; + + instance->aen_cmd = NULL; + megasas_return_cmd(instance, cmd); + + if ((instance->unload == 0) && + ((instance->issuepend_done == 1))) { + struct megasas_aen_event *ev; + ev = kzalloc(sizeof(*ev), GFP_ATOMIC); + if (!ev) { + printk(KERN_ERR "megasas_service_aen: out of memory\n"); + } else { + ev->instance = instance; + instance->ev = ev; + INIT_WORK(&ev->hotplug_work, megasas_aen_polling); + schedule_delayed_work( + (struct delayed_work *)&ev->hotplug_work, 0); + } + } +} + +/* + * Scsi host template for megaraid_sas driver + */ +static struct scsi_host_template megasas_template = { + + .module = THIS_MODULE, + .name = "LSI SAS based MegaRAID driver", + .proc_name = "megaraid_sas", + .slave_configure = megasas_slave_configure, + .slave_alloc = megasas_slave_alloc, + .queuecommand = megasas_queue_command, + .eh_device_reset_handler = megasas_reset_device, + .eh_bus_reset_handler = megasas_reset_bus_host, + .eh_host_reset_handler = megasas_reset_bus_host, + .eh_timed_out = megasas_reset_timer, + .bios_param = megasas_bios_param, + .use_clustering = ENABLE_CLUSTERING, +}; + +/** + * megasas_complete_int_cmd - Completes an internal command + * @instance: Adapter soft state + * @cmd: Command to be completed + * + * The megasas_issue_blocked_cmd() function waits for a command to complete + * after it issues a command. This function wakes up that waiting routine by + * calling wake_up() on the wait queue. + */ +static void +megasas_complete_int_cmd(struct megasas_instance *instance, + struct megasas_cmd *cmd) +{ + cmd->cmd_status = cmd->frame->io.cmd_status; + + if (cmd->cmd_status == ENODATA) { + cmd->cmd_status = 0; + } + wake_up(&instance->int_cmd_wait_q); +} + +/** + * megasas_complete_abort - Completes aborting a command + * @instance: Adapter soft state + * @cmd: Cmd that was issued to abort another cmd + * + * The megasas_issue_blocked_abort_cmd() function waits on abort_cmd_wait_q + * after it issues an abort on a previously issued command. This function + * wakes up all functions waiting on the same wait queue. + */ +static void +megasas_complete_abort(struct megasas_instance *instance, + struct megasas_cmd *cmd) +{ + if (cmd->sync_cmd) { + cmd->sync_cmd = 0; + cmd->cmd_status = 0; + wake_up(&instance->abort_cmd_wait_q); + } + + return; +} + +/** + * megasas_complete_cmd - Completes a command + * @instance: Adapter soft state + * @cmd: Command to be completed + * @alt_status: If non-zero, use this value as status to + * SCSI mid-layer instead of the value returned + * by the FW. This should be used if caller wants + * an alternate status (as in the case of aborted + * commands) + */ +static void +megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, + u8 alt_status) +{ + int exception = 0; + struct megasas_header *hdr = &cmd->frame->hdr; + unsigned long flags; + + /* flag for the retry reset */ + cmd->retry_for_fw_reset = 0; + + if (cmd->scmd) + cmd->scmd->SCp.ptr = NULL; + + switch (hdr->cmd) { + + case MFI_CMD_PD_SCSI_IO: + case MFI_CMD_LD_SCSI_IO: + + /* + * MFI_CMD_PD_SCSI_IO and MFI_CMD_LD_SCSI_IO could have been + * issued either through an IO path or an IOCTL path. If it + * was via IOCTL, we will send it to internal completion. + */ + if (cmd->sync_cmd) { + cmd->sync_cmd = 0; + megasas_complete_int_cmd(instance, cmd); + break; + } + + case MFI_CMD_LD_READ: + case MFI_CMD_LD_WRITE: + + if (alt_status) { + cmd->scmd->result = alt_status << 16; + exception = 1; + } + + if (exception) { + + atomic_dec(&instance->fw_outstanding); + + scsi_dma_unmap(cmd->scmd); + cmd->scmd->scsi_done(cmd->scmd); + megasas_return_cmd(instance, cmd); + + break; + } + + switch (hdr->cmd_status) { + + case MFI_STAT_OK: + cmd->scmd->result = DID_OK << 16; + break; + + case MFI_STAT_SCSI_IO_FAILED: + case MFI_STAT_LD_INIT_IN_PROGRESS: + cmd->scmd->result = + (DID_ERROR << 16) | hdr->scsi_status; + break; + + case MFI_STAT_SCSI_DONE_WITH_ERROR: + + cmd->scmd->result = (DID_OK << 16) | hdr->scsi_status; + + if (hdr->scsi_status == SAM_STAT_CHECK_CONDITION) { + memset(cmd->scmd->sense_buffer, 0, + SCSI_SENSE_BUFFERSIZE); + memcpy(cmd->scmd->sense_buffer, cmd->sense, + hdr->sense_len); + + cmd->scmd->result |= DRIVER_SENSE << 24; + } + + break; + + case MFI_STAT_LD_OFFLINE: + case MFI_STAT_DEVICE_NOT_FOUND: + cmd->scmd->result = DID_BAD_TARGET << 16; + break; + + default: + printk(KERN_DEBUG "megasas: MFI FW status %#x\n", + hdr->cmd_status); + cmd->scmd->result = DID_ERROR << 16; + break; + } + + atomic_dec(&instance->fw_outstanding); + + scsi_dma_unmap(cmd->scmd); + cmd->scmd->scsi_done(cmd->scmd); + megasas_return_cmd(instance, cmd); + + break; + + case MFI_CMD_SMP: + case MFI_CMD_STP: + case MFI_CMD_DCMD: + if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET_INFO || + cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET) { + spin_lock_irqsave(&poll_aen_lock, flags); + megasas_poll_wait_aen = 0; + spin_unlock_irqrestore(&poll_aen_lock, flags); + } + + /* + * See if got an event notification + */ + if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_WAIT) + megasas_service_aen(instance, cmd); + else + megasas_complete_int_cmd(instance, cmd); + + break; + + case MFI_CMD_ABORT: + /* + * Cmd issued to abort another cmd returned + */ + megasas_complete_abort(instance, cmd); + break; + + default: + printk("megasas: Unknown command completed! [0x%X]\n", + hdr->cmd); + break; + } +} + +/** + * megasas_issue_pending_cmds_again - issue all pending cmds + * in FW again because of the fw reset + * @instance: Adapter soft state + */ +static inline void +megasas_issue_pending_cmds_again(struct megasas_instance *instance) +{ + struct megasas_cmd *cmd; + struct list_head clist_local; + union megasas_evt_class_locale class_locale; + unsigned long flags; + u32 seq_num; + + INIT_LIST_HEAD(&clist_local); + spin_lock_irqsave(&instance->hba_lock, flags); + list_splice_init(&instance->internal_reset_pending_q, &clist_local); + spin_unlock_irqrestore(&instance->hba_lock, flags); + + while (!list_empty(&clist_local)) { + cmd = list_entry((&clist_local)->next, + struct megasas_cmd, list); + list_del_init(&cmd->list); + + if (cmd->sync_cmd || cmd->scmd) { + printk(KERN_NOTICE "megaraid_sas: command %p, %p:%d" + "detected to be pending while HBA reset.\n", + cmd, cmd->scmd, cmd->sync_cmd); + + cmd->retry_for_fw_reset++; + + if (cmd->retry_for_fw_reset == 3) { + printk(KERN_NOTICE "megaraid_sas: cmd %p, %p:%d" + "was tried multiple times during reset." + "Shutting down the HBA\n", + cmd, cmd->scmd, cmd->sync_cmd); + megaraid_sas_kill_hba(instance); + + instance->adprecovery = + MEGASAS_HW_CRITICAL_ERROR; + return; + } + } + + if (cmd->sync_cmd == 1) { + if (cmd->scmd) { + printk(KERN_NOTICE "megaraid_sas: unexpected" + "cmd attached to internal command!\n"); + } + printk(KERN_NOTICE "megasas: %p synchronous cmd" + "on the internal reset queue," + "issue it again.\n", cmd); + cmd->cmd_status = ENODATA; + instance->instancet->fire_cmd(instance, + cmd->frame_phys_addr , + 0, instance->reg_set); + } else if (cmd->scmd) { + printk(KERN_NOTICE "megasas: %p scsi cmd [%02x],%#lx" + "detected on the internal queue, issue again.\n", + cmd, cmd->scmd->cmnd[0], cmd->scmd->serial_number); + + atomic_inc(&instance->fw_outstanding); + instance->instancet->fire_cmd(instance, + cmd->frame_phys_addr, + cmd->frame_count-1, instance->reg_set); + } else { + printk(KERN_NOTICE "megasas: %p unexpected cmd on the" + "internal reset defer list while re-issue!!\n", + cmd); + } + } + + if (instance->aen_cmd) { + printk(KERN_NOTICE "megaraid_sas: aen_cmd in def process\n"); + megasas_return_cmd(instance, instance->aen_cmd); + + instance->aen_cmd = NULL; + } + + /* + * Initiate AEN (Asynchronous Event Notification) + */ + seq_num = instance->last_seq_num; + class_locale.members.reserved = 0; + class_locale.members.locale = MR_EVT_LOCALE_ALL; + class_locale.members.class = MR_EVT_CLASS_DEBUG; + + megasas_register_aen(instance, seq_num, class_locale.word); +} + +/** + * Move the internal reset pending commands to a deferred queue. + * + * We move the commands pending at internal reset time to a + * pending queue. This queue would be flushed after successful + * completion of the internal reset sequence. if the internal reset + * did not complete in time, the kernel reset handler would flush + * these commands. + **/ +static void +megasas_internal_reset_defer_cmds(struct megasas_instance *instance) +{ + struct megasas_cmd *cmd; + int i; + u32 max_cmd = instance->max_fw_cmds; + u32 defer_index; + unsigned long flags; + + defer_index = 0; + spin_lock_irqsave(&instance->cmd_pool_lock, flags); + for (i = 0; i < max_cmd; i++) { + cmd = instance->cmd_list[i]; + if (cmd->sync_cmd == 1 || cmd->scmd) { + printk(KERN_NOTICE "megasas: moving cmd[%d]:%p:%d:%p" + "on the defer queue as internal\n", + defer_index, cmd, cmd->sync_cmd, cmd->scmd); + + if (!list_empty(&cmd->list)) { + printk(KERN_NOTICE "megaraid_sas: ERROR while" + " moving this cmd:%p, %d %p, it was" + "discovered on some list?\n", + cmd, cmd->sync_cmd, cmd->scmd); + + list_del_init(&cmd->list); + } + defer_index++; + list_add_tail(&cmd->list, + &instance->internal_reset_pending_q); + } + } + spin_unlock_irqrestore(&instance->cmd_pool_lock, flags); +} + + +static void +process_fw_state_change_wq(struct work_struct *work) +{ + struct megasas_instance *instance = + container_of(work, struct megasas_instance, work_init); + u32 wait; + unsigned long flags; + + if (instance->adprecovery != MEGASAS_ADPRESET_SM_INFAULT) { + printk(KERN_NOTICE "megaraid_sas: error, recovery st %x \n", + instance->adprecovery); + return ; + } + + if (instance->adprecovery == MEGASAS_ADPRESET_SM_INFAULT) { + printk(KERN_NOTICE "megaraid_sas: FW detected to be in fault" + "state, restarting it...\n"); + + instance->instancet->disable_intr(instance->reg_set); + atomic_set(&instance->fw_outstanding, 0); + + atomic_set(&instance->fw_reset_no_pci_access, 1); + instance->instancet->adp_reset(instance, instance->reg_set); + atomic_set(&instance->fw_reset_no_pci_access, 0 ); + + printk(KERN_NOTICE "megaraid_sas: FW restarted successfully," + "initiating next stage...\n"); + + printk(KERN_NOTICE "megaraid_sas: HBA recovery state machine," + "state 2 starting...\n"); + + /*waitting for about 20 second before start the second init*/ + for (wait = 0; wait < 30; wait++) { + msleep(1000); + } + + if (megasas_transition_to_ready(instance)) { + printk(KERN_NOTICE "megaraid_sas:adapter not ready\n"); + + megaraid_sas_kill_hba(instance); + instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR; + return ; + } + + if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1064R) || + (instance->pdev->device == PCI_DEVICE_ID_DELL_PERC5) || + (instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR) + ) { + *instance->consumer = *instance->producer; + } else { + *instance->consumer = 0; + *instance->producer = 0; + } + + megasas_issue_init_mfi(instance); + + spin_lock_irqsave(&instance->hba_lock, flags); + instance->adprecovery = MEGASAS_HBA_OPERATIONAL; + spin_unlock_irqrestore(&instance->hba_lock, flags); + instance->instancet->enable_intr(instance->reg_set); + + megasas_issue_pending_cmds_again(instance); + instance->issuepend_done = 1; + } + return ; +} + +/** + * megasas_deplete_reply_queue - Processes all completed commands + * @instance: Adapter soft state + * @alt_status: Alternate status to be returned to + * SCSI mid-layer instead of the status + * returned by the FW + * Note: this must be called with hba lock held + */ +static int +megasas_deplete_reply_queue(struct megasas_instance *instance, + u8 alt_status) +{ + u32 mfiStatus; + u32 fw_state; + + if ((mfiStatus = instance->instancet->check_reset(instance, + instance->reg_set)) == 1) { + return IRQ_HANDLED; + } + + if ((mfiStatus = instance->instancet->clear_intr( + instance->reg_set) + ) == 0) { + return IRQ_NONE; + } + + instance->mfiStatus = mfiStatus; + + if ((mfiStatus & MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE)) { + fw_state = instance->instancet->read_fw_status_reg( + instance->reg_set) & MFI_STATE_MASK; + + if (fw_state != MFI_STATE_FAULT) { + printk(KERN_NOTICE "megaraid_sas: fw state:%x\n", + fw_state); + } + + if ((fw_state == MFI_STATE_FAULT) && + (instance->disableOnlineCtrlReset == 0)) { + printk(KERN_NOTICE "megaraid_sas: wait adp restart\n"); + + if ((instance->pdev->device == + PCI_DEVICE_ID_LSI_SAS1064R) || + (instance->pdev->device == + PCI_DEVICE_ID_DELL_PERC5) || + (instance->pdev->device == + PCI_DEVICE_ID_LSI_VERDE_ZCR)) { + + *instance->consumer = + MEGASAS_ADPRESET_INPROG_SIGN; + } + + + instance->instancet->disable_intr(instance->reg_set); + instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT; + instance->issuepend_done = 0; + + atomic_set(&instance->fw_outstanding, 0); + megasas_internal_reset_defer_cmds(instance); + + printk(KERN_NOTICE "megasas: fwState=%x, stage:%d\n", + fw_state, instance->adprecovery); + + schedule_work(&instance->work_init); + return IRQ_HANDLED; + + } else { + printk(KERN_NOTICE "megasas: fwstate:%x, dis_OCR=%x\n", + fw_state, instance->disableOnlineCtrlReset); + } + } + + tasklet_schedule(&instance->isr_tasklet); + return IRQ_HANDLED; +} +/** + * megasas_isr - isr entry point + */ +static irqreturn_t megasas_isr(int irq, void *devp) +{ + struct megasas_instance *instance; + unsigned long flags; + irqreturn_t rc; + + if (atomic_read( + &(((struct megasas_instance *)devp)->fw_reset_no_pci_access))) + return IRQ_HANDLED; + + instance = (struct megasas_instance *)devp; + + spin_lock_irqsave(&instance->hba_lock, flags); + rc = megasas_deplete_reply_queue(instance, DID_OK); + spin_unlock_irqrestore(&instance->hba_lock, flags); + + return rc; +} + +/** + * megasas_transition_to_ready - Move the FW to READY state + * @instance: Adapter soft state + * + * During the initialization, FW passes can potentially be in any one of + * several possible states. If the FW in operational, waiting-for-handshake + * states, driver must take steps to bring it to ready state. Otherwise, it + * has to wait for the ready state. + */ +static int +megasas_transition_to_ready(struct megasas_instance* instance) +{ + int i; + u8 max_wait; + u32 fw_state; + u32 cur_state; + u32 abs_state, curr_abs_state; + + fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK; + + if (fw_state != MFI_STATE_READY) + printk(KERN_INFO "megasas: Waiting for FW to come to ready" + " state\n"); + + while (fw_state != MFI_STATE_READY) { + + abs_state = + instance->instancet->read_fw_status_reg(instance->reg_set); + + switch (fw_state) { + + case MFI_STATE_FAULT: + + printk(KERN_DEBUG "megasas: FW in FAULT state!!\n"); + return -ENODEV; + + case MFI_STATE_WAIT_HANDSHAKE: + /* + * Set the CLR bit in inbound doorbell + */ + if ((instance->pdev->device == + PCI_DEVICE_ID_LSI_SAS0073SKINNY) || + (instance->pdev->device == + PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { + + writel( + MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG, + &instance->reg_set->reserved_0[0]); + } else { + writel( + MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG, + &instance->reg_set->inbound_doorbell); + } + + max_wait = MEGASAS_RESET_WAIT_TIME; + cur_state = MFI_STATE_WAIT_HANDSHAKE; + break; + + case MFI_STATE_BOOT_MESSAGE_PENDING: + if ((instance->pdev->device == + PCI_DEVICE_ID_LSI_SAS0073SKINNY) || + (instance->pdev->device == + PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { + writel(MFI_INIT_HOTPLUG, + &instance->reg_set->reserved_0[0]); + } else + writel(MFI_INIT_HOTPLUG, + &instance->reg_set->inbound_doorbell); + + max_wait = MEGASAS_RESET_WAIT_TIME; + cur_state = MFI_STATE_BOOT_MESSAGE_PENDING; + break; + + case MFI_STATE_OPERATIONAL: + /* + * Bring it to READY state; assuming max wait 10 secs + */ + instance->instancet->disable_intr(instance->reg_set); + if ((instance->pdev->device == + PCI_DEVICE_ID_LSI_SAS0073SKINNY) || + (instance->pdev->device == + PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { + writel(MFI_RESET_FLAGS, + &instance->reg_set->reserved_0[0]); + } else + writel(MFI_RESET_FLAGS, + &instance->reg_set->inbound_doorbell); + + max_wait = MEGASAS_RESET_WAIT_TIME; + cur_state = MFI_STATE_OPERATIONAL; + break; + + case MFI_STATE_UNDEFINED: + /* + * This state should not last for more than 2 seconds + */ + max_wait = MEGASAS_RESET_WAIT_TIME; + cur_state = MFI_STATE_UNDEFINED; + break; + + case MFI_STATE_BB_INIT: + max_wait = MEGASAS_RESET_WAIT_TIME; + cur_state = MFI_STATE_BB_INIT; + break; + + case MFI_STATE_FW_INIT: + max_wait = MEGASAS_RESET_WAIT_TIME; + cur_state = MFI_STATE_FW_INIT; + break; + + case MFI_STATE_FW_INIT_2: + max_wait = MEGASAS_RESET_WAIT_TIME; + cur_state = MFI_STATE_FW_INIT_2; + break; + + case MFI_STATE_DEVICE_SCAN: + max_wait = MEGASAS_RESET_WAIT_TIME; + cur_state = MFI_STATE_DEVICE_SCAN; + break; + + case MFI_STATE_FLUSH_CACHE: + max_wait = MEGASAS_RESET_WAIT_TIME; + cur_state = MFI_STATE_FLUSH_CACHE; + break; + + default: + printk(KERN_DEBUG "megasas: Unknown state 0x%x\n", + fw_state); + return -ENODEV; + } + + /* + * The cur_state should not last for more than max_wait secs + */ + for (i = 0; i < (max_wait * 1000); i++) { + fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & + MFI_STATE_MASK ; + curr_abs_state = + instance->instancet->read_fw_status_reg(instance->reg_set); + + if (abs_state == curr_abs_state) { + msleep(1); + } else + break; + } + + /* + * Return error if fw_state hasn't changed after max_wait + */ + if (curr_abs_state == abs_state) { + printk(KERN_DEBUG "FW state [%d] hasn't changed " + "in %d secs\n", fw_state, max_wait); + return -ENODEV; + } + } + printk(KERN_INFO "megasas: FW now in Ready state\n"); + + return 0; +} + +/** + * megasas_teardown_frame_pool - Destroy the cmd frame DMA pool + * @instance: Adapter soft state + */ +static void megasas_teardown_frame_pool(struct megasas_instance *instance) +{ + int i; + u32 max_cmd = instance->max_fw_cmds; + struct megasas_cmd *cmd; + + if (!instance->frame_dma_pool) + return; + + /* + * Return all frames to pool + */ + for (i = 0; i < max_cmd; i++) { + + cmd = instance->cmd_list[i]; + + if (cmd->frame) + pci_pool_free(instance->frame_dma_pool, cmd->frame, + cmd->frame_phys_addr); + + if (cmd->sense) + pci_pool_free(instance->sense_dma_pool, cmd->sense, + cmd->sense_phys_addr); + } + + /* + * Now destroy the pool itself + */ + pci_pool_destroy(instance->frame_dma_pool); + pci_pool_destroy(instance->sense_dma_pool); + + instance->frame_dma_pool = NULL; + instance->sense_dma_pool = NULL; +} + +/** + * megasas_create_frame_pool - Creates DMA pool for cmd frames + * @instance: Adapter soft state + * + * Each command packet has an embedded DMA memory buffer that is used for + * filling MFI frame and the SG list that immediately follows the frame. This + * function creates those DMA memory buffers for each command packet by using + * PCI pool facility. + */ +static int megasas_create_frame_pool(struct megasas_instance *instance) +{ + int i; + u32 max_cmd; + u32 sge_sz; + u32 sgl_sz; + u32 total_sz; + u32 frame_count; + struct megasas_cmd *cmd; + + max_cmd = instance->max_fw_cmds; + + /* + * Size of our frame is 64 bytes for MFI frame, followed by max SG + * elements and finally SCSI_SENSE_BUFFERSIZE bytes for sense buffer + */ + sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : + sizeof(struct megasas_sge32); + + if (instance->flag_ieee) { + sge_sz = sizeof(struct megasas_sge_skinny); + } + + /* + * Calculated the number of 64byte frames required for SGL + */ + sgl_sz = sge_sz * instance->max_num_sge; + frame_count = (sgl_sz + MEGAMFI_FRAME_SIZE - 1) / MEGAMFI_FRAME_SIZE; + frame_count = 15; + + /* + * We need one extra frame for the MFI command + */ + frame_count++; + + total_sz = MEGAMFI_FRAME_SIZE * frame_count; + /* + * Use DMA pool facility provided by PCI layer + */ + instance->frame_dma_pool = pci_pool_create("megasas frame pool", + instance->pdev, total_sz, 64, + 0); + + if (!instance->frame_dma_pool) { + printk(KERN_DEBUG "megasas: failed to setup frame pool\n"); + return -ENOMEM; + } + + instance->sense_dma_pool = pci_pool_create("megasas sense pool", + instance->pdev, 128, 4, 0); + + if (!instance->sense_dma_pool) { + printk(KERN_DEBUG "megasas: failed to setup sense pool\n"); + + pci_pool_destroy(instance->frame_dma_pool); + instance->frame_dma_pool = NULL; + + return -ENOMEM; + } + + /* + * Allocate and attach a frame to each of the commands in cmd_list. + * By making cmd->index as the context instead of the &cmd, we can + * always use 32bit context regardless of the architecture + */ + for (i = 0; i < max_cmd; i++) { + + cmd = instance->cmd_list[i]; + + cmd->frame = pci_pool_alloc(instance->frame_dma_pool, + GFP_KERNEL, &cmd->frame_phys_addr); + + cmd->sense = pci_pool_alloc(instance->sense_dma_pool, + GFP_KERNEL, &cmd->sense_phys_addr); + + /* + * megasas_teardown_frame_pool() takes care of freeing + * whatever has been allocated + */ + if (!cmd->frame || !cmd->sense) { + printk(KERN_DEBUG "megasas: pci_pool_alloc failed \n"); + megasas_teardown_frame_pool(instance); + return -ENOMEM; + } + + memset(cmd->frame, 0, total_sz); + cmd->frame->io.context = cmd->index; + cmd->frame->io.pad_0 = 0; + } + + return 0; +} + +/** + * megasas_free_cmds - Free all the cmds in the free cmd pool + * @instance: Adapter soft state + */ +static void megasas_free_cmds(struct megasas_instance *instance) +{ + int i; + /* First free the MFI frame pool */ + megasas_teardown_frame_pool(instance); + + /* Free all the commands in the cmd_list */ + for (i = 0; i < instance->max_fw_cmds; i++) + kfree(instance->cmd_list[i]); + + /* Free the cmd_list buffer itself */ + kfree(instance->cmd_list); + instance->cmd_list = NULL; + + INIT_LIST_HEAD(&instance->cmd_pool); +} + +/** + * megasas_alloc_cmds - Allocates the command packets + * @instance: Adapter soft state + * + * Each command that is issued to the FW, whether IO commands from the OS or + * internal commands like IOCTLs, are wrapped in local data structure called + * megasas_cmd. The frame embedded in this megasas_cmd is actually issued to + * the FW. + * + * Each frame has a 32-bit field called context (tag). This context is used + * to get back the megasas_cmd from the frame when a frame gets completed in + * the ISR. Typically the address of the megasas_cmd itself would be used as + * the context. But we wanted to keep the differences between 32 and 64 bit + * systems to the mininum. We always use 32 bit integers for the context. In + * this driver, the 32 bit values are the indices into an array cmd_list. + * This array is used only to look up the megasas_cmd given the context. The + * free commands themselves are maintained in a linked list called cmd_pool. + */ +static int megasas_alloc_cmds(struct megasas_instance *instance) +{ + int i; + int j; + u32 max_cmd; + struct megasas_cmd *cmd; + + max_cmd = instance->max_fw_cmds; + + /* + * instance->cmd_list is an array of struct megasas_cmd pointers. + * Allocate the dynamic array first and then allocate individual + * commands. + */ + instance->cmd_list = kcalloc(max_cmd, sizeof(struct megasas_cmd*), GFP_KERNEL); + + if (!instance->cmd_list) { + printk(KERN_DEBUG "megasas: out of memory\n"); + return -ENOMEM; + } + + + for (i = 0; i < max_cmd; i++) { + instance->cmd_list[i] = kmalloc(sizeof(struct megasas_cmd), + GFP_KERNEL); + + if (!instance->cmd_list[i]) { + + for (j = 0; j < i; j++) + kfree(instance->cmd_list[j]); + + kfree(instance->cmd_list); + instance->cmd_list = NULL; + + return -ENOMEM; + } + } + + /* + * Add all the commands to command pool (instance->cmd_pool) + */ + for (i = 0; i < max_cmd; i++) { + cmd = instance->cmd_list[i]; + memset(cmd, 0, sizeof(struct megasas_cmd)); + cmd->index = i; + cmd->scmd = NULL; + cmd->instance = instance; + + list_add_tail(&cmd->list, &instance->cmd_pool); + } + + /* + * Create a frame pool and assign one frame to each cmd + */ + if (megasas_create_frame_pool(instance)) { + printk(KERN_DEBUG "megasas: Error creating frame DMA pool\n"); + megasas_free_cmds(instance); + } + + return 0; +} + +/* + * megasas_get_pd_list_info - Returns FW's pd_list structure + * @instance: Adapter soft state + * @pd_list: pd_list structure + * + * Issues an internal command (DCMD) to get the FW's controller PD + * list structure. This information is mainly used to find out SYSTEM + * supported by the FW. + */ +static int +megasas_get_pd_list(struct megasas_instance *instance) +{ + int ret = 0, pd_index = 0; + struct megasas_cmd *cmd; + struct megasas_dcmd_frame *dcmd; + struct MR_PD_LIST *ci; + struct MR_PD_ADDRESS *pd_addr; + dma_addr_t ci_h = 0; + + cmd = megasas_get_cmd(instance); + + if (!cmd) { + printk(KERN_DEBUG "megasas (get_pd_list): Failed to get cmd\n"); + return -ENOMEM; + } + + dcmd = &cmd->frame->dcmd; + + ci = pci_alloc_consistent(instance->pdev, + MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), &ci_h); + + if (!ci) { + printk(KERN_DEBUG "Failed to alloc mem for pd_list\n"); + megasas_return_cmd(instance, cmd); + return -ENOMEM; + } + + memset(ci, 0, sizeof(*ci)); + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); + + dcmd->mbox.b[0] = MR_PD_QUERY_TYPE_EXPOSED_TO_HOST; + dcmd->mbox.b[1] = 0; + dcmd->cmd = MFI_CMD_DCMD; + dcmd->cmd_status = 0xFF; + dcmd->sge_count = 1; + dcmd->flags = MFI_FRAME_DIR_READ; + dcmd->timeout = 0; + dcmd->pad_0 = 0; + dcmd->data_xfer_len = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST); + dcmd->opcode = MR_DCMD_PD_LIST_QUERY; + dcmd->sgl.sge32[0].phys_addr = ci_h; + dcmd->sgl.sge32[0].length = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST); + + if (!megasas_issue_polled(instance, cmd)) { + ret = 0; + } else { + ret = -1; + } + + /* + * the following function will get the instance PD LIST. + */ + + pd_addr = ci->addr; + + if ( ret == 0 && + (ci->count < + (MEGASAS_MAX_PD_CHANNELS * MEGASAS_MAX_DEV_PER_CHANNEL))) { + + memset(instance->pd_list, 0, + MEGASAS_MAX_PD * sizeof(struct megasas_pd_list)); + + for (pd_index = 0; pd_index < ci->count; pd_index++) { + + instance->pd_list[pd_addr->deviceId].tid = + pd_addr->deviceId; + instance->pd_list[pd_addr->deviceId].driveType = + pd_addr->scsiDevType; + instance->pd_list[pd_addr->deviceId].driveState = + MR_PD_STATE_SYSTEM; + pd_addr++; + } + } + + pci_free_consistent(instance->pdev, + MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), + ci, ci_h); + megasas_return_cmd(instance, cmd); + + return ret; +} + +/* + * megasas_get_ld_list_info - Returns FW's ld_list structure + * @instance: Adapter soft state + * @ld_list: ld_list structure + * + * Issues an internal command (DCMD) to get the FW's controller PD + * list structure. This information is mainly used to find out SYSTEM + * supported by the FW. + */ +static int +megasas_get_ld_list(struct megasas_instance *instance) +{ + int ret = 0, ld_index = 0, ids = 0; + struct megasas_cmd *cmd; + struct megasas_dcmd_frame *dcmd; + struct MR_LD_LIST *ci; + dma_addr_t ci_h = 0; + + cmd = megasas_get_cmd(instance); + + if (!cmd) { + printk(KERN_DEBUG "megasas_get_ld_list: Failed to get cmd\n"); + return -ENOMEM; + } + + dcmd = &cmd->frame->dcmd; + + ci = pci_alloc_consistent(instance->pdev, + sizeof(struct MR_LD_LIST), + &ci_h); + + if (!ci) { + printk(KERN_DEBUG "Failed to alloc mem in get_ld_list\n"); + megasas_return_cmd(instance, cmd); + return -ENOMEM; + } + + memset(ci, 0, sizeof(*ci)); + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); + + dcmd->cmd = MFI_CMD_DCMD; + dcmd->cmd_status = 0xFF; + dcmd->sge_count = 1; + dcmd->flags = MFI_FRAME_DIR_READ; + dcmd->timeout = 0; + dcmd->data_xfer_len = sizeof(struct MR_LD_LIST); + dcmd->opcode = MR_DCMD_LD_GET_LIST; + dcmd->sgl.sge32[0].phys_addr = ci_h; + dcmd->sgl.sge32[0].length = sizeof(struct MR_LD_LIST); + dcmd->pad_0 = 0; + + if (!megasas_issue_polled(instance, cmd)) { + ret = 0; + } else { + ret = -1; + } + + /* the following function will get the instance PD LIST */ + + if ((ret == 0) && (ci->ldCount <= MAX_LOGICAL_DRIVES)) { + memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS); + + for (ld_index = 0; ld_index < ci->ldCount; ld_index++) { + if (ci->ldList[ld_index].state != 0) { + ids = ci->ldList[ld_index].ref.targetId; + instance->ld_ids[ids] = + ci->ldList[ld_index].ref.targetId; + } + } + } + + pci_free_consistent(instance->pdev, + sizeof(struct MR_LD_LIST), + ci, + ci_h); + + megasas_return_cmd(instance, cmd); + return ret; +} + +/** + * megasas_get_controller_info - Returns FW's controller structure + * @instance: Adapter soft state + * @ctrl_info: Controller information structure + * + * Issues an internal command (DCMD) to get the FW's controller structure. + * This information is mainly used to find out the maximum IO transfer per + * command supported by the FW. + */ +static int +megasas_get_ctrl_info(struct megasas_instance *instance, + struct megasas_ctrl_info *ctrl_info) +{ + int ret = 0; + struct megasas_cmd *cmd; + struct megasas_dcmd_frame *dcmd; + struct megasas_ctrl_info *ci; + dma_addr_t ci_h = 0; + + cmd = megasas_get_cmd(instance); + + if (!cmd) { + printk(KERN_DEBUG "megasas: Failed to get a free cmd\n"); + return -ENOMEM; + } + + dcmd = &cmd->frame->dcmd; + + ci = pci_alloc_consistent(instance->pdev, + sizeof(struct megasas_ctrl_info), &ci_h); + + if (!ci) { + printk(KERN_DEBUG "Failed to alloc mem for ctrl info\n"); + megasas_return_cmd(instance, cmd); + return -ENOMEM; + } + + memset(ci, 0, sizeof(*ci)); + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); + + dcmd->cmd = MFI_CMD_DCMD; + dcmd->cmd_status = 0xFF; + dcmd->sge_count = 1; + dcmd->flags = MFI_FRAME_DIR_READ; + dcmd->timeout = 0; + dcmd->pad_0 = 0; + dcmd->data_xfer_len = sizeof(struct megasas_ctrl_info); + dcmd->opcode = MR_DCMD_CTRL_GET_INFO; + dcmd->sgl.sge32[0].phys_addr = ci_h; + dcmd->sgl.sge32[0].length = sizeof(struct megasas_ctrl_info); + + if (!megasas_issue_polled(instance, cmd)) { + ret = 0; + memcpy(ctrl_info, ci, sizeof(struct megasas_ctrl_info)); + } else { + ret = -1; + } + + pci_free_consistent(instance->pdev, sizeof(struct megasas_ctrl_info), + ci, ci_h); + + megasas_return_cmd(instance, cmd); + return ret; +} + +/** + * megasas_issue_init_mfi - Initializes the FW + * @instance: Adapter soft state + * + * Issues the INIT MFI cmd + */ +static int +megasas_issue_init_mfi(struct megasas_instance *instance) +{ + u32 context; + + struct megasas_cmd *cmd; + + struct megasas_init_frame *init_frame; + struct megasas_init_queue_info *initq_info; + dma_addr_t init_frame_h; + dma_addr_t initq_info_h; + + /* + * Prepare a init frame. Note the init frame points to queue info + * structure. Each frame has SGL allocated after first 64 bytes. For + * this frame - since we don't need any SGL - we use SGL's space as + * queue info structure + * + * We will not get a NULL command below. We just created the pool. + */ + cmd = megasas_get_cmd(instance); + + init_frame = (struct megasas_init_frame *)cmd->frame; + initq_info = (struct megasas_init_queue_info *) + ((unsigned long)init_frame + 64); + + init_frame_h = cmd->frame_phys_addr; + initq_info_h = init_frame_h + 64; + + context = init_frame->context; + memset(init_frame, 0, MEGAMFI_FRAME_SIZE); + memset(initq_info, 0, sizeof(struct megasas_init_queue_info)); + init_frame->context = context; + + initq_info->reply_queue_entries = instance->max_fw_cmds + 1; + initq_info->reply_queue_start_phys_addr_lo = instance->reply_queue_h; + + initq_info->producer_index_phys_addr_lo = instance->producer_h; + initq_info->consumer_index_phys_addr_lo = instance->consumer_h; + + init_frame->cmd = MFI_CMD_INIT; + init_frame->cmd_status = 0xFF; + init_frame->queue_info_new_phys_addr_lo = initq_info_h; + + init_frame->data_xfer_len = sizeof(struct megasas_init_queue_info); + + /* + * disable the intr before firing the init frame to FW + */ + instance->instancet->disable_intr(instance->reg_set); + + /* + * Issue the init frame in polled mode + */ + + if (megasas_issue_polled(instance, cmd)) { + printk(KERN_ERR "megasas: Failed to init firmware\n"); + megasas_return_cmd(instance, cmd); + goto fail_fw_init; + } + + megasas_return_cmd(instance, cmd); + + return 0; + +fail_fw_init: + return -EINVAL; +} + +/** + * megasas_start_timer - Initializes a timer object + * @instance: Adapter soft state + * @timer: timer object to be initialized + * @fn: timer function + * @interval: time interval between timer function call + */ +static inline void +megasas_start_timer(struct megasas_instance *instance, + struct timer_list *timer, + void *fn, unsigned long interval) +{ + init_timer(timer); + timer->expires = jiffies + interval; + timer->data = (unsigned long)instance; + timer->function = fn; + add_timer(timer); +} + +/** + * megasas_io_completion_timer - Timer fn + * @instance_addr: Address of adapter soft state + * + * Schedules tasklet for cmd completion + * if poll_mode_io is set + */ +static void +megasas_io_completion_timer(unsigned long instance_addr) +{ + struct megasas_instance *instance = + (struct megasas_instance *)instance_addr; + + if (atomic_read(&instance->fw_outstanding)) + tasklet_schedule(&instance->isr_tasklet); + + /* Restart timer */ + if (poll_mode_io) + mod_timer(&instance->io_completion_timer, + jiffies + MEGASAS_COMPLETION_TIMER_INTERVAL); +} + +/** + * megasas_init_mfi - Initializes the FW + * @instance: Adapter soft state + * + * This is the main function for initializing MFI firmware. + */ +static int megasas_init_mfi(struct megasas_instance *instance) +{ + u32 context_sz; + u32 reply_q_sz; + u32 max_sectors_1; + u32 max_sectors_2; + u32 tmp_sectors; + struct megasas_register_set __iomem *reg_set; + struct megasas_ctrl_info *ctrl_info; + /* + * Map the message registers + */ + if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078GEN2) || + (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) || + (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || + (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0079GEN2)) { + instance->base_addr = pci_resource_start(instance->pdev, 1); + } else { + instance->base_addr = pci_resource_start(instance->pdev, 0); + } + + if (pci_request_selected_regions(instance->pdev, + pci_select_bars(instance->pdev, IORESOURCE_MEM), + "megasas: LSI")) { + printk(KERN_DEBUG "megasas: IO memory region busy!\n"); + return -EBUSY; + } + + instance->reg_set = ioremap_nocache(instance->base_addr, 8192); + + if (!instance->reg_set) { + printk(KERN_DEBUG "megasas: Failed to map IO mem\n"); + goto fail_ioremap; + } + + reg_set = instance->reg_set; + + switch(instance->pdev->device) + { + case PCI_DEVICE_ID_LSI_SAS1078R: + case PCI_DEVICE_ID_LSI_SAS1078DE: + instance->instancet = &megasas_instance_template_ppc; + break; + case PCI_DEVICE_ID_LSI_SAS1078GEN2: + case PCI_DEVICE_ID_LSI_SAS0079GEN2: + instance->instancet = &megasas_instance_template_gen2; + break; + case PCI_DEVICE_ID_LSI_SAS0073SKINNY: + case PCI_DEVICE_ID_LSI_SAS0071SKINNY: + instance->instancet = &megasas_instance_template_skinny; + break; + case PCI_DEVICE_ID_LSI_SAS1064R: + case PCI_DEVICE_ID_DELL_PERC5: + default: + instance->instancet = &megasas_instance_template_xscale; + break; + } + + /* + * We expect the FW state to be READY + */ + if (megasas_transition_to_ready(instance)) + goto fail_ready_state; + + /* + * Get various operational parameters from status register + */ + instance->max_fw_cmds = instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF; + /* + * Reduce the max supported cmds by 1. This is to ensure that the + * reply_q_sz (1 more than the max cmd that driver may send) + * does not exceed max cmds that the FW can support + */ + instance->max_fw_cmds = instance->max_fw_cmds-1; + instance->max_num_sge = (instance->instancet->read_fw_status_reg(reg_set) & 0xFF0000) >> + 0x10; + /* + * Create a pool of commands + */ + if (megasas_alloc_cmds(instance)) + goto fail_alloc_cmds; + + /* + * Allocate memory for reply queue. Length of reply queue should + * be _one_ more than the maximum commands handled by the firmware. + * + * Note: When FW completes commands, it places corresponding contex + * values in this circular reply queue. This circular queue is a fairly + * typical producer-consumer queue. FW is the producer (of completed + * commands) and the driver is the consumer. + */ + context_sz = sizeof(u32); + reply_q_sz = context_sz * (instance->max_fw_cmds + 1); + + instance->reply_queue = pci_alloc_consistent(instance->pdev, + reply_q_sz, + &instance->reply_queue_h); + + if (!instance->reply_queue) { + printk(KERN_DEBUG "megasas: Out of DMA mem for reply queue\n"); + goto fail_reply_queue; + } + + if (megasas_issue_init_mfi(instance)) + goto fail_fw_init; + + instance->fw_support_ieee = 0; + instance->fw_support_ieee = + (instance->instancet->read_fw_status_reg(reg_set) & + 0x04000000); + + printk(KERN_NOTICE "megasas_init_mfi: fw_support_ieee=%d", + instance->fw_support_ieee); + + if (instance->fw_support_ieee) + instance->flag_ieee = 1; + + /** for passthrough + * the following function will get the PD LIST. + */ + + memset(instance->pd_list, 0 , + (MEGASAS_MAX_PD * sizeof(struct megasas_pd_list))); + megasas_get_pd_list(instance); + + memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS); + megasas_get_ld_list(instance); + + ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL); + + /* + * Compute the max allowed sectors per IO: The controller info has two + * limits on max sectors. Driver should use the minimum of these two. + * + * 1 << stripe_sz_ops.min = max sectors per strip + * + * Note that older firmwares ( < FW ver 30) didn't report information + * to calculate max_sectors_1. So the number ended up as zero always. + */ + tmp_sectors = 0; + if (ctrl_info && !megasas_get_ctrl_info(instance, ctrl_info)) { + + max_sectors_1 = (1 << ctrl_info->stripe_sz_ops.min) * + ctrl_info->max_strips_per_io; + max_sectors_2 = ctrl_info->max_request_size; + + tmp_sectors = min_t(u32, max_sectors_1 , max_sectors_2); + instance->disableOnlineCtrlReset = + ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset; + } + + instance->max_sectors_per_req = instance->max_num_sge * + PAGE_SIZE / 512; + if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors)) + instance->max_sectors_per_req = tmp_sectors; + + kfree(ctrl_info); + + /* + * Setup tasklet for cmd completion + */ + + tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc, + (unsigned long)instance); + + /* Initialize the cmd completion timer */ + if (poll_mode_io) + megasas_start_timer(instance, &instance->io_completion_timer, + megasas_io_completion_timer, + MEGASAS_COMPLETION_TIMER_INTERVAL); + return 0; + + fail_fw_init: + + pci_free_consistent(instance->pdev, reply_q_sz, + instance->reply_queue, instance->reply_queue_h); + fail_reply_queue: + megasas_free_cmds(instance); + + fail_alloc_cmds: + fail_ready_state: + iounmap(instance->reg_set); + + fail_ioremap: + pci_release_selected_regions(instance->pdev, + pci_select_bars(instance->pdev, IORESOURCE_MEM)); + + return -EINVAL; +} + +/** + * megasas_release_mfi - Reverses the FW initialization + * @intance: Adapter soft state + */ +static void megasas_release_mfi(struct megasas_instance *instance) +{ + u32 reply_q_sz = sizeof(u32) * (instance->max_fw_cmds + 1); + + pci_free_consistent(instance->pdev, reply_q_sz, + instance->reply_queue, instance->reply_queue_h); + + megasas_free_cmds(instance); + + iounmap(instance->reg_set); + + pci_release_selected_regions(instance->pdev, + pci_select_bars(instance->pdev, IORESOURCE_MEM)); +} + +/** + * megasas_get_seq_num - Gets latest event sequence numbers + * @instance: Adapter soft state + * @eli: FW event log sequence numbers information + * + * FW maintains a log of all events in a non-volatile area. Upper layers would + * usually find out the latest sequence number of the events, the seq number at + * the boot etc. They would "read" all the events below the latest seq number + * by issuing a direct fw cmd (DCMD). For the future events (beyond latest seq + * number), they would subsribe to AEN (asynchronous event notification) and + * wait for the events to happen. + */ +static int +megasas_get_seq_num(struct megasas_instance *instance, + struct megasas_evt_log_info *eli) +{ + struct megasas_cmd *cmd; + struct megasas_dcmd_frame *dcmd; + struct megasas_evt_log_info *el_info; + dma_addr_t el_info_h = 0; + + cmd = megasas_get_cmd(instance); + + if (!cmd) { + return -ENOMEM; + } + + dcmd = &cmd->frame->dcmd; + el_info = pci_alloc_consistent(instance->pdev, + sizeof(struct megasas_evt_log_info), + &el_info_h); + + if (!el_info) { + megasas_return_cmd(instance, cmd); + return -ENOMEM; + } + + memset(el_info, 0, sizeof(*el_info)); + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); + + dcmd->cmd = MFI_CMD_DCMD; + dcmd->cmd_status = 0x0; + dcmd->sge_count = 1; + dcmd->flags = MFI_FRAME_DIR_READ; + dcmd->timeout = 0; + dcmd->pad_0 = 0; + dcmd->data_xfer_len = sizeof(struct megasas_evt_log_info); + dcmd->opcode = MR_DCMD_CTRL_EVENT_GET_INFO; + dcmd->sgl.sge32[0].phys_addr = el_info_h; + dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_log_info); + + megasas_issue_blocked_cmd(instance, cmd); + + /* + * Copy the data back into callers buffer + */ + memcpy(eli, el_info, sizeof(struct megasas_evt_log_info)); + + pci_free_consistent(instance->pdev, sizeof(struct megasas_evt_log_info), + el_info, el_info_h); + + megasas_return_cmd(instance, cmd); + + return 0; +} + +/** + * megasas_register_aen - Registers for asynchronous event notification + * @instance: Adapter soft state + * @seq_num: The starting sequence number + * @class_locale: Class of the event + * + * This function subscribes for AEN for events beyond the @seq_num. It requests + * to be notified if and only if the event is of type @class_locale + */ +static int +megasas_register_aen(struct megasas_instance *instance, u32 seq_num, + u32 class_locale_word) +{ + int ret_val; + struct megasas_cmd *cmd; + struct megasas_dcmd_frame *dcmd; + union megasas_evt_class_locale curr_aen; + union megasas_evt_class_locale prev_aen; + + /* + * If there an AEN pending already (aen_cmd), check if the + * class_locale of that pending AEN is inclusive of the new + * AEN request we currently have. If it is, then we don't have + * to do anything. In other words, whichever events the current + * AEN request is subscribing to, have already been subscribed + * to. + * + * If the old_cmd is _not_ inclusive, then we have to abort + * that command, form a class_locale that is superset of both + * old and current and re-issue to the FW + */ + + curr_aen.word = class_locale_word; + + if (instance->aen_cmd) { + + prev_aen.word = instance->aen_cmd->frame->dcmd.mbox.w[1]; + + /* + * A class whose enum value is smaller is inclusive of all + * higher values. If a PROGRESS (= -1) was previously + * registered, then a new registration requests for higher + * classes need not be sent to FW. They are automatically + * included. + * + * Locale numbers don't have such hierarchy. They are bitmap + * values + */ + if ((prev_aen.members.class <= curr_aen.members.class) && + !((prev_aen.members.locale & curr_aen.members.locale) ^ + curr_aen.members.locale)) { + /* + * Previously issued event registration includes + * current request. Nothing to do. + */ + return 0; + } else { + curr_aen.members.locale |= prev_aen.members.locale; + + if (prev_aen.members.class < curr_aen.members.class) + curr_aen.members.class = prev_aen.members.class; + + instance->aen_cmd->abort_aen = 1; + ret_val = megasas_issue_blocked_abort_cmd(instance, + instance-> + aen_cmd); + + if (ret_val) { + printk(KERN_DEBUG "megasas: Failed to abort " + "previous AEN command\n"); + return ret_val; + } + } + } + + cmd = megasas_get_cmd(instance); + + if (!cmd) + return -ENOMEM; + + dcmd = &cmd->frame->dcmd; + + memset(instance->evt_detail, 0, sizeof(struct megasas_evt_detail)); + + /* + * Prepare DCMD for aen registration + */ + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); + + dcmd->cmd = MFI_CMD_DCMD; + dcmd->cmd_status = 0x0; + dcmd->sge_count = 1; + dcmd->flags = MFI_FRAME_DIR_READ; + dcmd->timeout = 0; + dcmd->pad_0 = 0; + instance->last_seq_num = seq_num; + dcmd->data_xfer_len = sizeof(struct megasas_evt_detail); + dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT; + dcmd->mbox.w[0] = seq_num; + dcmd->mbox.w[1] = curr_aen.word; + dcmd->sgl.sge32[0].phys_addr = (u32) instance->evt_detail_h; + dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_detail); + + if (instance->aen_cmd != NULL) { + megasas_return_cmd(instance, cmd); + return 0; + } + + /* + * Store reference to the cmd used to register for AEN. When an + * application wants us to register for AEN, we have to abort this + * cmd and re-register with a new EVENT LOCALE supplied by that app + */ + instance->aen_cmd = cmd; + + /* + * Issue the aen registration frame + */ + instance->instancet->fire_cmd(instance, + cmd->frame_phys_addr, 0, instance->reg_set); + + return 0; +} + +/** + * megasas_start_aen - Subscribes to AEN during driver load time + * @instance: Adapter soft state + */ +static int megasas_start_aen(struct megasas_instance *instance) +{ + struct megasas_evt_log_info eli; + union megasas_evt_class_locale class_locale; + + /* + * Get the latest sequence number from FW + */ + memset(&eli, 0, sizeof(eli)); + + if (megasas_get_seq_num(instance, &eli)) + return -1; + + /* + * Register AEN with FW for latest sequence number plus 1 + */ + class_locale.members.reserved = 0; + class_locale.members.locale = MR_EVT_LOCALE_ALL; + class_locale.members.class = MR_EVT_CLASS_DEBUG; + + return megasas_register_aen(instance, eli.newest_seq_num + 1, + class_locale.word); +} + +/** + * megasas_io_attach - Attaches this driver to SCSI mid-layer + * @instance: Adapter soft state + */ +static int megasas_io_attach(struct megasas_instance *instance) +{ + struct Scsi_Host *host = instance->host; + + /* + * Export parameters required by SCSI mid-layer + */ + host->irq = instance->pdev->irq; + host->unique_id = instance->unique_id; + if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || + (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { + host->can_queue = + instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS; + } else + host->can_queue = + instance->max_fw_cmds - MEGASAS_INT_CMDS; + host->this_id = instance->init_id; + host->sg_tablesize = instance->max_num_sge; + /* + * Check if the module parameter value for max_sectors can be used + */ + if (max_sectors && max_sectors < instance->max_sectors_per_req) + instance->max_sectors_per_req = max_sectors; + else { + if (max_sectors) { + if (((instance->pdev->device == + PCI_DEVICE_ID_LSI_SAS1078GEN2) || + (instance->pdev->device == + PCI_DEVICE_ID_LSI_SAS0079GEN2)) && + (max_sectors <= MEGASAS_MAX_SECTORS)) { + instance->max_sectors_per_req = max_sectors; + } else { + printk(KERN_INFO "megasas: max_sectors should be > 0" + "and <= %d (or < 1MB for GEN2 controller)\n", + instance->max_sectors_per_req); + } + } + } + + host->max_sectors = instance->max_sectors_per_req; + host->cmd_per_lun = 128; + host->max_channel = MEGASAS_MAX_CHANNELS - 1; + host->max_id = MEGASAS_MAX_DEV_PER_CHANNEL; + host->max_lun = MEGASAS_MAX_LUN; + host->max_cmd_len = 16; + + /* + * Notify the mid-layer about the new controller + */ + if (scsi_add_host(host, &instance->pdev->dev)) { + printk(KERN_DEBUG "megasas: scsi_add_host failed\n"); + return -ENODEV; + } + + /* + * Trigger SCSI to scan our drives + */ + scsi_scan_host(host); + return 0; +} + +static int +megasas_set_dma_mask(struct pci_dev *pdev) +{ + /* + * All our contollers are capable of performing 64-bit DMA + */ + if (IS_DMA64) { + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) { + + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) + goto fail_set_dma_mask; + } + } else { + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) + goto fail_set_dma_mask; + } + return 0; + +fail_set_dma_mask: + return 1; +} + +/** + * megasas_probe_one - PCI hotplug entry point + * @pdev: PCI device structure + * @id: PCI ids of supported hotplugged adapter + */ +static int __devinit +megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) +{ + int rval; + struct Scsi_Host *host; + struct megasas_instance *instance; + + /* + * Announce PCI information + */ + printk(KERN_INFO "megasas: %#4.04x:%#4.04x:%#4.04x:%#4.04x: ", + pdev->vendor, pdev->device, pdev->subsystem_vendor, + pdev->subsystem_device); + + printk("bus %d:slot %d:func %d\n", + pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + + /* + * PCI prepping: enable device set bus mastering and dma mask + */ + rval = pci_enable_device_mem(pdev); + + if (rval) { + return rval; + } + + pci_set_master(pdev); + + if (megasas_set_dma_mask(pdev)) + goto fail_set_dma_mask; + + host = scsi_host_alloc(&megasas_template, + sizeof(struct megasas_instance)); + + if (!host) { + printk(KERN_DEBUG "megasas: scsi_host_alloc failed\n"); + goto fail_alloc_instance; + } + + instance = (struct megasas_instance *)host->hostdata; + memset(instance, 0, sizeof(*instance)); + atomic_set( &instance->fw_reset_no_pci_access, 0 ); + + instance->producer = pci_alloc_consistent(pdev, sizeof(u32), + &instance->producer_h); + instance->consumer = pci_alloc_consistent(pdev, sizeof(u32), + &instance->consumer_h); + + if (!instance->producer || !instance->consumer) { + printk(KERN_DEBUG "megasas: Failed to allocate memory for " + "producer, consumer\n"); + goto fail_alloc_dma_buf; + } + + *instance->producer = 0; + *instance->consumer = 0; + megasas_poll_wait_aen = 0; + instance->flag_ieee = 0; + instance->ev = NULL; + instance->issuepend_done = 1; + instance->adprecovery = MEGASAS_HBA_OPERATIONAL; + megasas_poll_wait_aen = 0; + + instance->evt_detail = pci_alloc_consistent(pdev, + sizeof(struct + megasas_evt_detail), + &instance->evt_detail_h); + + if (!instance->evt_detail) { + printk(KERN_DEBUG "megasas: Failed to allocate memory for " + "event detail structure\n"); + goto fail_alloc_dma_buf; + } + + /* + * Initialize locks and queues + */ + INIT_LIST_HEAD(&instance->cmd_pool); + INIT_LIST_HEAD(&instance->internal_reset_pending_q); + + atomic_set(&instance->fw_outstanding,0); + + init_waitqueue_head(&instance->int_cmd_wait_q); + init_waitqueue_head(&instance->abort_cmd_wait_q); + + spin_lock_init(&instance->cmd_pool_lock); + spin_lock_init(&instance->hba_lock); + spin_lock_init(&instance->completion_lock); + spin_lock_init(&poll_aen_lock); + + mutex_init(&instance->aen_mutex); + + /* + * Initialize PCI related and misc parameters + */ + instance->pdev = pdev; + instance->host = host; + instance->unique_id = pdev->bus->number << 8 | pdev->devfn; + instance->init_id = MEGASAS_DEFAULT_INIT_ID; + + if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || + (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { + instance->flag_ieee = 1; + sema_init(&instance->ioctl_sem, MEGASAS_SKINNY_INT_CMDS); + } else + sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS); + + megasas_dbg_lvl = 0; + instance->flag = 0; + instance->unload = 1; + instance->last_time = 0; + instance->disableOnlineCtrlReset = 1; + + INIT_WORK(&instance->work_init, process_fw_state_change_wq); + + /* + * Initialize MFI Firmware + */ + if (megasas_init_mfi(instance)) + goto fail_init_mfi; + + /* + * Register IRQ + */ + if (request_irq(pdev->irq, megasas_isr, IRQF_SHARED, "megasas", instance)) { + printk(KERN_DEBUG "megasas: Failed to register IRQ\n"); + goto fail_irq; + } + + instance->instancet->enable_intr(instance->reg_set); + + /* + * Store instance in PCI softstate + */ + pci_set_drvdata(pdev, instance); + + /* + * Add this controller to megasas_mgmt_info structure so that it + * can be exported to management applications + */ + megasas_mgmt_info.count++; + megasas_mgmt_info.instance[megasas_mgmt_info.max_index] = instance; + megasas_mgmt_info.max_index++; + + /* + * Initiate AEN (Asynchronous Event Notification) + */ + if (megasas_start_aen(instance)) { + printk(KERN_DEBUG "megasas: start aen failed\n"); + goto fail_start_aen; + } + + /* + * Register with SCSI mid-layer + */ + if (megasas_io_attach(instance)) + goto fail_io_attach; + + instance->unload = 0; + return 0; + + fail_start_aen: + fail_io_attach: + megasas_mgmt_info.count--; + megasas_mgmt_info.instance[megasas_mgmt_info.max_index] = NULL; + megasas_mgmt_info.max_index--; + + pci_set_drvdata(pdev, NULL); + instance->instancet->disable_intr(instance->reg_set); + free_irq(instance->pdev->irq, instance); + + megasas_release_mfi(instance); + + fail_irq: + fail_init_mfi: + fail_alloc_dma_buf: + if (instance->evt_detail) + pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), + instance->evt_detail, + instance->evt_detail_h); + + if (instance->producer) + pci_free_consistent(pdev, sizeof(u32), instance->producer, + instance->producer_h); + if (instance->consumer) + pci_free_consistent(pdev, sizeof(u32), instance->consumer, + instance->consumer_h); + scsi_host_put(host); + + fail_alloc_instance: + fail_set_dma_mask: + pci_disable_device(pdev); + + return -ENODEV; +} + +/** + * megasas_flush_cache - Requests FW to flush all its caches + * @instance: Adapter soft state + */ +static void megasas_flush_cache(struct megasas_instance *instance) +{ + struct megasas_cmd *cmd; + struct megasas_dcmd_frame *dcmd; + + if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) + return; + + cmd = megasas_get_cmd(instance); + + if (!cmd) + return; + + dcmd = &cmd->frame->dcmd; + + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); + + dcmd->cmd = MFI_CMD_DCMD; + dcmd->cmd_status = 0x0; + dcmd->sge_count = 0; + dcmd->flags = MFI_FRAME_DIR_NONE; + dcmd->timeout = 0; + dcmd->pad_0 = 0; + dcmd->data_xfer_len = 0; + dcmd->opcode = MR_DCMD_CTRL_CACHE_FLUSH; + dcmd->mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE; + + megasas_issue_blocked_cmd(instance, cmd); + + megasas_return_cmd(instance, cmd); + + return; +} + +/** + * megasas_shutdown_controller - Instructs FW to shutdown the controller + * @instance: Adapter soft state + * @opcode: Shutdown/Hibernate + */ +static void megasas_shutdown_controller(struct megasas_instance *instance, + u32 opcode) +{ + struct megasas_cmd *cmd; + struct megasas_dcmd_frame *dcmd; + + if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) + return; + + cmd = megasas_get_cmd(instance); + + if (!cmd) + return; + + if (instance->aen_cmd) + megasas_issue_blocked_abort_cmd(instance, instance->aen_cmd); + + dcmd = &cmd->frame->dcmd; + + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); + + dcmd->cmd = MFI_CMD_DCMD; + dcmd->cmd_status = 0x0; + dcmd->sge_count = 0; + dcmd->flags = MFI_FRAME_DIR_NONE; + dcmd->timeout = 0; + dcmd->pad_0 = 0; + dcmd->data_xfer_len = 0; + dcmd->opcode = opcode; + + megasas_issue_blocked_cmd(instance, cmd); + + megasas_return_cmd(instance, cmd); + + return; +} + +#ifdef CONFIG_PM +/** + * megasas_suspend - driver suspend entry point + * @pdev: PCI device structure + * @state: PCI power state to suspend routine + */ +static int +megasas_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct Scsi_Host *host; + struct megasas_instance *instance; + + instance = pci_get_drvdata(pdev); + host = instance->host; + instance->unload = 1; + + if (poll_mode_io) + del_timer_sync(&instance->io_completion_timer); + + megasas_flush_cache(instance); + megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN); + + /* cancel the delayed work if this work still in queue */ + if (instance->ev != NULL) { + struct megasas_aen_event *ev = instance->ev; + cancel_delayed_work( + (struct delayed_work *)&ev->hotplug_work); + flush_scheduled_work(); + instance->ev = NULL; + } + + tasklet_kill(&instance->isr_tasklet); + + pci_set_drvdata(instance->pdev, instance); + instance->instancet->disable_intr(instance->reg_set); + free_irq(instance->pdev->irq, instance); + + pci_save_state(pdev); + pci_disable_device(pdev); + + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + + return 0; +} + +/** + * megasas_resume- driver resume entry point + * @pdev: PCI device structure + */ +static int +megasas_resume(struct pci_dev *pdev) +{ + int rval; + struct Scsi_Host *host; + struct megasas_instance *instance; + + instance = pci_get_drvdata(pdev); + host = instance->host; + pci_set_power_state(pdev, PCI_D0); + pci_enable_wake(pdev, PCI_D0, 0); + pci_restore_state(pdev); + + /* + * PCI prepping: enable device set bus mastering and dma mask + */ + rval = pci_enable_device_mem(pdev); + + if (rval) { + printk(KERN_ERR "megasas: Enable device failed\n"); + return rval; + } + + pci_set_master(pdev); + + if (megasas_set_dma_mask(pdev)) + goto fail_set_dma_mask; + + /* + * Initialize MFI Firmware + */ + + *instance->producer = 0; + *instance->consumer = 0; + + atomic_set(&instance->fw_outstanding, 0); + + /* + * We expect the FW state to be READY + */ + if (megasas_transition_to_ready(instance)) + goto fail_ready_state; + + if (megasas_issue_init_mfi(instance)) + goto fail_init_mfi; + + tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc, + (unsigned long)instance); + + /* + * Register IRQ + */ + if (request_irq(pdev->irq, megasas_isr, IRQF_SHARED, + "megasas", instance)) { + printk(KERN_ERR "megasas: Failed to register IRQ\n"); + goto fail_irq; + } + + instance->instancet->enable_intr(instance->reg_set); + + /* + * Initiate AEN (Asynchronous Event Notification) + */ + if (megasas_start_aen(instance)) + printk(KERN_ERR "megasas: Start AEN failed\n"); + + /* Initialize the cmd completion timer */ + if (poll_mode_io) + megasas_start_timer(instance, &instance->io_completion_timer, + megasas_io_completion_timer, + MEGASAS_COMPLETION_TIMER_INTERVAL); + instance->unload = 0; + + return 0; + +fail_irq: +fail_init_mfi: + if (instance->evt_detail) + pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), + instance->evt_detail, + instance->evt_detail_h); + + if (instance->producer) + pci_free_consistent(pdev, sizeof(u32), instance->producer, + instance->producer_h); + if (instance->consumer) + pci_free_consistent(pdev, sizeof(u32), instance->consumer, + instance->consumer_h); + scsi_host_put(host); + +fail_set_dma_mask: +fail_ready_state: + + pci_disable_device(pdev); + + return -ENODEV; +} +#else +#define megasas_suspend NULL +#define megasas_resume NULL +#endif + +/** + * megasas_detach_one - PCI hot"un"plug entry point + * @pdev: PCI device structure + */ +static void __devexit megasas_detach_one(struct pci_dev *pdev) +{ + int i; + struct Scsi_Host *host; + struct megasas_instance *instance; + + instance = pci_get_drvdata(pdev); + instance->unload = 1; + host = instance->host; + + if (poll_mode_io) + del_timer_sync(&instance->io_completion_timer); + + scsi_remove_host(instance->host); + megasas_flush_cache(instance); + megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); + + /* cancel the delayed work if this work still in queue*/ + if (instance->ev != NULL) { + struct megasas_aen_event *ev = instance->ev; + cancel_delayed_work( + (struct delayed_work *)&ev->hotplug_work); + flush_scheduled_work(); + instance->ev = NULL; + } + + tasklet_kill(&instance->isr_tasklet); + + /* + * Take the instance off the instance array. Note that we will not + * decrement the max_index. We let this array be sparse array + */ + for (i = 0; i < megasas_mgmt_info.max_index; i++) { + if (megasas_mgmt_info.instance[i] == instance) { + megasas_mgmt_info.count--; + megasas_mgmt_info.instance[i] = NULL; + + break; + } + } + + pci_set_drvdata(instance->pdev, NULL); + + instance->instancet->disable_intr(instance->reg_set); + + free_irq(instance->pdev->irq, instance); + + megasas_release_mfi(instance); + + pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), + instance->evt_detail, instance->evt_detail_h); + + pci_free_consistent(pdev, sizeof(u32), instance->producer, + instance->producer_h); + + pci_free_consistent(pdev, sizeof(u32), instance->consumer, + instance->consumer_h); + + scsi_host_put(host); + + pci_set_drvdata(pdev, NULL); + + pci_disable_device(pdev); + + return; +} + +/** + * megasas_shutdown - Shutdown entry point + * @device: Generic device structure + */ +static void megasas_shutdown(struct pci_dev *pdev) +{ + struct megasas_instance *instance = pci_get_drvdata(pdev); + instance->unload = 1; + megasas_flush_cache(instance); + megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); +} + +/** + * megasas_mgmt_open - char node "open" entry point + */ +static int megasas_mgmt_open(struct inode *inode, struct file *filep) +{ + /* + * Allow only those users with admin rights + */ + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + return 0; +} + +/** + * megasas_mgmt_fasync - Async notifier registration from applications + * + * This function adds the calling process to a driver global queue. When an + * event occurs, SIGIO will be sent to all processes in this queue. + */ +static int megasas_mgmt_fasync(int fd, struct file *filep, int mode) +{ + int rc; + + mutex_lock(&megasas_async_queue_mutex); + + rc = fasync_helper(fd, filep, mode, &megasas_async_queue); + + mutex_unlock(&megasas_async_queue_mutex); + + if (rc >= 0) { + /* For sanity check when we get ioctl */ + filep->private_data = filep; + return 0; + } + + printk(KERN_DEBUG "megasas: fasync_helper failed [%d]\n", rc); + + return rc; +} + +/** + * megasas_mgmt_poll - char node "poll" entry point + * */ +static unsigned int megasas_mgmt_poll(struct file *file, poll_table *wait) +{ + unsigned int mask; + unsigned long flags; + poll_wait(file, &megasas_poll_wait, wait); + spin_lock_irqsave(&poll_aen_lock, flags); + if (megasas_poll_wait_aen) + mask = (POLLIN | POLLRDNORM); + else + mask = 0; + spin_unlock_irqrestore(&poll_aen_lock, flags); + return mask; +} + +/** + * megasas_mgmt_fw_ioctl - Issues management ioctls to FW + * @instance: Adapter soft state + * @argp: User's ioctl packet + */ +static int +megasas_mgmt_fw_ioctl(struct megasas_instance *instance, + struct megasas_iocpacket __user * user_ioc, + struct megasas_iocpacket *ioc) +{ + struct megasas_sge32 *kern_sge32; + struct megasas_cmd *cmd; + void *kbuff_arr[MAX_IOCTL_SGE]; + dma_addr_t buf_handle = 0; + int error = 0, i; + void *sense = NULL; + dma_addr_t sense_handle; + unsigned long *sense_ptr; + + memset(kbuff_arr, 0, sizeof(kbuff_arr)); + + if (ioc->sge_count > MAX_IOCTL_SGE) { + printk(KERN_DEBUG "megasas: SGE count [%d] > max limit [%d]\n", + ioc->sge_count, MAX_IOCTL_SGE); + return -EINVAL; + } + + cmd = megasas_get_cmd(instance); + if (!cmd) { + printk(KERN_DEBUG "megasas: Failed to get a cmd packet\n"); + return -ENOMEM; + } + + /* + * User's IOCTL packet has 2 frames (maximum). Copy those two + * frames into our cmd's frames. cmd->frame's context will get + * overwritten when we copy from user's frames. So set that value + * alone separately + */ + memcpy(cmd->frame, ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE); + cmd->frame->hdr.context = cmd->index; + cmd->frame->hdr.pad_0 = 0; + + /* + * The management interface between applications and the fw uses + * MFI frames. E.g, RAID configuration changes, LD property changes + * etc are accomplishes through different kinds of MFI frames. The + * driver needs to care only about substituting user buffers with + * kernel buffers in SGLs. The location of SGL is embedded in the + * struct iocpacket itself. + */ + kern_sge32 = (struct megasas_sge32 *) + ((unsigned long)cmd->frame + ioc->sgl_off); + + /* + * For each user buffer, create a mirror buffer and copy in + */ + for (i = 0; i < ioc->sge_count; i++) { + kbuff_arr[i] = dma_alloc_coherent(&instance->pdev->dev, + ioc->sgl[i].iov_len, + &buf_handle, GFP_KERNEL); + if (!kbuff_arr[i]) { + printk(KERN_DEBUG "megasas: Failed to alloc " + "kernel SGL buffer for IOCTL \n"); + error = -ENOMEM; + goto out; + } + + /* + * We don't change the dma_coherent_mask, so + * pci_alloc_consistent only returns 32bit addresses + */ + kern_sge32[i].phys_addr = (u32) buf_handle; + kern_sge32[i].length = ioc->sgl[i].iov_len; + + /* + * We created a kernel buffer corresponding to the + * user buffer. Now copy in from the user buffer + */ + if (copy_from_user(kbuff_arr[i], ioc->sgl[i].iov_base, + (u32) (ioc->sgl[i].iov_len))) { + error = -EFAULT; + goto out; + } + } + + if (ioc->sense_len) { + sense = dma_alloc_coherent(&instance->pdev->dev, ioc->sense_len, + &sense_handle, GFP_KERNEL); + if (!sense) { + error = -ENOMEM; + goto out; + } + + sense_ptr = + (unsigned long *) ((unsigned long)cmd->frame + ioc->sense_off); + *sense_ptr = sense_handle; + } + + /* + * Set the sync_cmd flag so that the ISR knows not to complete this + * cmd to the SCSI mid-layer + */ + cmd->sync_cmd = 1; + megasas_issue_blocked_cmd(instance, cmd); + cmd->sync_cmd = 0; + + /* + * copy out the kernel buffers to user buffers + */ + for (i = 0; i < ioc->sge_count; i++) { + if (copy_to_user(ioc->sgl[i].iov_base, kbuff_arr[i], + ioc->sgl[i].iov_len)) { + error = -EFAULT; + goto out; + } + } + + /* + * copy out the sense + */ + if (ioc->sense_len) { + /* + * sense_ptr points to the location that has the user + * sense buffer address + */ + sense_ptr = (unsigned long *) ((unsigned long)ioc->frame.raw + + ioc->sense_off); + + if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)), + sense, ioc->sense_len)) { + printk(KERN_ERR "megasas: Failed to copy out to user " + "sense data\n"); + error = -EFAULT; + goto out; + } + } + + /* + * copy the status codes returned by the fw + */ + if (copy_to_user(&user_ioc->frame.hdr.cmd_status, + &cmd->frame->hdr.cmd_status, sizeof(u8))) { + printk(KERN_DEBUG "megasas: Error copying out cmd_status\n"); + error = -EFAULT; + } + + out: + if (sense) { + dma_free_coherent(&instance->pdev->dev, ioc->sense_len, + sense, sense_handle); + } + + for (i = 0; i < ioc->sge_count && kbuff_arr[i]; i++) { + dma_free_coherent(&instance->pdev->dev, + kern_sge32[i].length, + kbuff_arr[i], kern_sge32[i].phys_addr); + } + + megasas_return_cmd(instance, cmd); + return error; +} + +static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg) +{ + struct megasas_iocpacket __user *user_ioc = + (struct megasas_iocpacket __user *)arg; + struct megasas_iocpacket *ioc; + struct megasas_instance *instance; + int error; + int i; + unsigned long flags; + u32 wait_time = MEGASAS_RESET_WAIT_TIME; + + ioc = kmalloc(sizeof(*ioc), GFP_KERNEL); + if (!ioc) + return -ENOMEM; + + if (copy_from_user(ioc, user_ioc, sizeof(*ioc))) { + error = -EFAULT; + goto out_kfree_ioc; + } + + instance = megasas_lookup_instance(ioc->host_no); + if (!instance) { + error = -ENODEV; + goto out_kfree_ioc; + } + + if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) { + printk(KERN_ERR "Controller in crit error\n"); + error = -ENODEV; + goto out_kfree_ioc; + } + + if (instance->unload == 1) { + error = -ENODEV; + goto out_kfree_ioc; + } + + /* + * We will allow only MEGASAS_INT_CMDS number of parallel ioctl cmds + */ + if (down_interruptible(&instance->ioctl_sem)) { + error = -ERESTARTSYS; + goto out_kfree_ioc; + } + + for (i = 0; i < wait_time; i++) { + + spin_lock_irqsave(&instance->hba_lock, flags); + if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) { + spin_unlock_irqrestore(&instance->hba_lock, flags); + break; + } + spin_unlock_irqrestore(&instance->hba_lock, flags); + + if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { + printk(KERN_NOTICE "megasas: waiting" + "for controller reset to finish\n"); + } + + msleep(1000); + } + + spin_lock_irqsave(&instance->hba_lock, flags); + if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) { + spin_unlock_irqrestore(&instance->hba_lock, flags); + + printk(KERN_ERR "megaraid_sas: timed out while" + "waiting for HBA to recover\n"); + error = -ENODEV; + goto out_kfree_ioc; + } + spin_unlock_irqrestore(&instance->hba_lock, flags); + + error = megasas_mgmt_fw_ioctl(instance, user_ioc, ioc); + up(&instance->ioctl_sem); + + out_kfree_ioc: + kfree(ioc); + return error; +} + +static int megasas_mgmt_ioctl_aen(struct file *file, unsigned long arg) +{ + struct megasas_instance *instance; + struct megasas_aen aen; + int error; + int i; + unsigned long flags; + u32 wait_time = MEGASAS_RESET_WAIT_TIME; + + if (file->private_data != file) { + printk(KERN_DEBUG "megasas: fasync_helper was not " + "called first\n"); + return -EINVAL; + } + + if (copy_from_user(&aen, (void __user *)arg, sizeof(aen))) + return -EFAULT; + + instance = megasas_lookup_instance(aen.host_no); + + if (!instance) + return -ENODEV; + + if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) { + return -ENODEV; + } + + if (instance->unload == 1) { + return -ENODEV; + } + + for (i = 0; i < wait_time; i++) { + + spin_lock_irqsave(&instance->hba_lock, flags); + if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) { + spin_unlock_irqrestore(&instance->hba_lock, + flags); + break; + } + + spin_unlock_irqrestore(&instance->hba_lock, flags); + + if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { + printk(KERN_NOTICE "megasas: waiting for" + "controller reset to finish\n"); + } + + msleep(1000); + } + + spin_lock_irqsave(&instance->hba_lock, flags); + if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) { + spin_unlock_irqrestore(&instance->hba_lock, flags); + printk(KERN_ERR "megaraid_sas: timed out while waiting" + "for HBA to recover.\n"); + return -ENODEV; + } + spin_unlock_irqrestore(&instance->hba_lock, flags); + + mutex_lock(&instance->aen_mutex); + error = megasas_register_aen(instance, aen.seq_num, + aen.class_locale_word); + mutex_unlock(&instance->aen_mutex); + return error; +} + +/** + * megasas_mgmt_ioctl - char node ioctl entry point + */ +static long +megasas_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case MEGASAS_IOC_FIRMWARE: + return megasas_mgmt_ioctl_fw(file, arg); + + case MEGASAS_IOC_GET_AEN: + return megasas_mgmt_ioctl_aen(file, arg); + } + + return -ENOTTY; +} + +#ifdef CONFIG_COMPAT +static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg) +{ + struct compat_megasas_iocpacket __user *cioc = + (struct compat_megasas_iocpacket __user *)arg; + struct megasas_iocpacket __user *ioc = + compat_alloc_user_space(sizeof(struct megasas_iocpacket)); + int i; + int error = 0; + compat_uptr_t ptr; + + if (clear_user(ioc, sizeof(*ioc))) + return -EFAULT; + + if (copy_in_user(&ioc->host_no, &cioc->host_no, sizeof(u16)) || + copy_in_user(&ioc->sgl_off, &cioc->sgl_off, sizeof(u32)) || + copy_in_user(&ioc->sense_off, &cioc->sense_off, sizeof(u32)) || + copy_in_user(&ioc->sense_len, &cioc->sense_len, sizeof(u32)) || + copy_in_user(ioc->frame.raw, cioc->frame.raw, 128) || + copy_in_user(&ioc->sge_count, &cioc->sge_count, sizeof(u32))) + return -EFAULT; + + /* + * The sense_ptr is used in megasas_mgmt_fw_ioctl only when + * sense_len is not null, so prepare the 64bit value under + * the same condition. + */ + if (ioc->sense_len) { + void __user **sense_ioc_ptr = + (void __user **)(ioc->frame.raw + ioc->sense_off); + compat_uptr_t *sense_cioc_ptr = + (compat_uptr_t *)(cioc->frame.raw + cioc->sense_off); + if (get_user(ptr, sense_cioc_ptr) || + put_user(compat_ptr(ptr), sense_ioc_ptr)) + return -EFAULT; + } + + for (i = 0; i < MAX_IOCTL_SGE; i++) { + if (get_user(ptr, &cioc->sgl[i].iov_base) || + put_user(compat_ptr(ptr), &ioc->sgl[i].iov_base) || + copy_in_user(&ioc->sgl[i].iov_len, + &cioc->sgl[i].iov_len, sizeof(compat_size_t))) + return -EFAULT; + } + + error = megasas_mgmt_ioctl_fw(file, (unsigned long)ioc); + + if (copy_in_user(&cioc->frame.hdr.cmd_status, + &ioc->frame.hdr.cmd_status, sizeof(u8))) { + printk(KERN_DEBUG "megasas: error copy_in_user cmd_status\n"); + return -EFAULT; + } + return error; +} + +static long +megasas_mgmt_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + switch (cmd) { + case MEGASAS_IOC_FIRMWARE32: + return megasas_mgmt_compat_ioctl_fw(file, arg); + case MEGASAS_IOC_GET_AEN: + return megasas_mgmt_ioctl_aen(file, arg); + } + + return -ENOTTY; +} +#endif + +/* + * File operations structure for management interface + */ +static const struct file_operations megasas_mgmt_fops = { + .owner = THIS_MODULE, + .open = megasas_mgmt_open, + .fasync = megasas_mgmt_fasync, + .unlocked_ioctl = megasas_mgmt_ioctl, + .poll = megasas_mgmt_poll, +#ifdef CONFIG_COMPAT + .compat_ioctl = megasas_mgmt_compat_ioctl, +#endif + .llseek = noop_llseek, +}; + +/* + * PCI hotplug support registration structure + */ +static struct pci_driver megasas_pci_driver = { + + .name = "megaraid_sas", + .id_table = megasas_pci_table, + .probe = megasas_probe_one, + .remove = __devexit_p(megasas_detach_one), + .suspend = megasas_suspend, + .resume = megasas_resume, + .shutdown = megasas_shutdown, +}; + +/* + * Sysfs driver attributes + */ +static ssize_t megasas_sysfs_show_version(struct device_driver *dd, char *buf) +{ + return snprintf(buf, strlen(MEGASAS_VERSION) + 2, "%s\n", + MEGASAS_VERSION); +} + +static DRIVER_ATTR(version, S_IRUGO, megasas_sysfs_show_version, NULL); + +static ssize_t +megasas_sysfs_show_release_date(struct device_driver *dd, char *buf) +{ + return snprintf(buf, strlen(MEGASAS_RELDATE) + 2, "%s\n", + MEGASAS_RELDATE); +} + +static DRIVER_ATTR(release_date, S_IRUGO, megasas_sysfs_show_release_date, + NULL); + +static ssize_t +megasas_sysfs_show_support_poll_for_event(struct device_driver *dd, char *buf) +{ + return sprintf(buf, "%u\n", support_poll_for_event); +} + +static DRIVER_ATTR(support_poll_for_event, S_IRUGO, + megasas_sysfs_show_support_poll_for_event, NULL); + + static ssize_t +megasas_sysfs_show_support_device_change(struct device_driver *dd, char *buf) +{ + return sprintf(buf, "%u\n", support_device_change); +} + +static DRIVER_ATTR(support_device_change, S_IRUGO, + megasas_sysfs_show_support_device_change, NULL); + +static ssize_t +megasas_sysfs_show_dbg_lvl(struct device_driver *dd, char *buf) +{ + return sprintf(buf, "%u\n", megasas_dbg_lvl); +} + +static ssize_t +megasas_sysfs_set_dbg_lvl(struct device_driver *dd, const char *buf, size_t count) +{ + int retval = count; + if(sscanf(buf,"%u",&megasas_dbg_lvl)<1){ + printk(KERN_ERR "megasas: could not set dbg_lvl\n"); + retval = -EINVAL; + } + return retval; +} + +static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUSR, megasas_sysfs_show_dbg_lvl, + megasas_sysfs_set_dbg_lvl); + +static ssize_t +megasas_sysfs_show_poll_mode_io(struct device_driver *dd, char *buf) +{ + return sprintf(buf, "%u\n", poll_mode_io); +} + +static ssize_t +megasas_sysfs_set_poll_mode_io(struct device_driver *dd, + const char *buf, size_t count) +{ + int retval = count; + int tmp = poll_mode_io; + int i; + struct megasas_instance *instance; + + if (sscanf(buf, "%u", &poll_mode_io) < 1) { + printk(KERN_ERR "megasas: could not set poll_mode_io\n"); + retval = -EINVAL; + } + + /* + * Check if poll_mode_io is already set or is same as previous value + */ + if ((tmp && poll_mode_io) || (tmp == poll_mode_io)) + goto out; + + if (poll_mode_io) { + /* + * Start timers for all adapters + */ + for (i = 0; i < megasas_mgmt_info.max_index; i++) { + instance = megasas_mgmt_info.instance[i]; + if (instance) { + megasas_start_timer(instance, + &instance->io_completion_timer, + megasas_io_completion_timer, + MEGASAS_COMPLETION_TIMER_INTERVAL); + } + } + } else { + /* + * Delete timers for all adapters + */ + for (i = 0; i < megasas_mgmt_info.max_index; i++) { + instance = megasas_mgmt_info.instance[i]; + if (instance) + del_timer_sync(&instance->io_completion_timer); + } + } + +out: + return retval; +} + +static void +megasas_aen_polling(struct work_struct *work) +{ + struct megasas_aen_event *ev = + container_of(work, struct megasas_aen_event, hotplug_work); + struct megasas_instance *instance = ev->instance; + union megasas_evt_class_locale class_locale; + struct Scsi_Host *host; + struct scsi_device *sdev1; + u16 pd_index = 0; + u16 ld_index = 0; + int i, j, doscan = 0; + u32 seq_num; + int error; + + if (!instance) { + printk(KERN_ERR "invalid instance!\n"); + kfree(ev); + return; + } + instance->ev = NULL; + host = instance->host; + if (instance->evt_detail) { + + switch (instance->evt_detail->code) { + case MR_EVT_PD_INSERTED: + if (megasas_get_pd_list(instance) == 0) { + for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) { + for (j = 0; + j < MEGASAS_MAX_DEV_PER_CHANNEL; + j++) { + + pd_index = + (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; + + sdev1 = + scsi_device_lookup(host, i, j, 0); + + if (instance->pd_list[pd_index].driveState + == MR_PD_STATE_SYSTEM) { + if (!sdev1) { + scsi_add_device(host, i, j, 0); + } + + if (sdev1) + scsi_device_put(sdev1); + } + } + } + } + doscan = 0; + break; + + case MR_EVT_PD_REMOVED: + if (megasas_get_pd_list(instance) == 0) { + megasas_get_pd_list(instance); + for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) { + for (j = 0; + j < MEGASAS_MAX_DEV_PER_CHANNEL; + j++) { + + pd_index = + (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; + + sdev1 = + scsi_device_lookup(host, i, j, 0); + + if (instance->pd_list[pd_index].driveState + == MR_PD_STATE_SYSTEM) { + if (sdev1) { + scsi_device_put(sdev1); + } + } else { + if (sdev1) { + scsi_remove_device(sdev1); + scsi_device_put(sdev1); + } + } + } + } + } + doscan = 0; + break; + + case MR_EVT_LD_OFFLINE: + case MR_EVT_LD_DELETED: + megasas_get_ld_list(instance); + for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { + for (j = 0; + j < MEGASAS_MAX_DEV_PER_CHANNEL; + j++) { + + ld_index = + (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; + + sdev1 = scsi_device_lookup(host, + i + MEGASAS_MAX_LD_CHANNELS, + j, + 0); + + if (instance->ld_ids[ld_index] != 0xff) { + if (sdev1) { + scsi_device_put(sdev1); + } + } else { + if (sdev1) { + scsi_remove_device(sdev1); + scsi_device_put(sdev1); + } + } + } + } + doscan = 0; + break; + case MR_EVT_LD_CREATED: + megasas_get_ld_list(instance); + for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { + for (j = 0; + j < MEGASAS_MAX_DEV_PER_CHANNEL; + j++) { + ld_index = + (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; + + sdev1 = scsi_device_lookup(host, + i+MEGASAS_MAX_LD_CHANNELS, + j, 0); + + if (instance->ld_ids[ld_index] != + 0xff) { + if (!sdev1) { + scsi_add_device(host, + i + 2, + j, 0); + } + } + if (sdev1) { + scsi_device_put(sdev1); + } + } + } + doscan = 0; + break; + case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED: + case MR_EVT_FOREIGN_CFG_IMPORTED: + doscan = 1; + break; + default: + doscan = 0; + break; + } + } else { + printk(KERN_ERR "invalid evt_detail!\n"); + kfree(ev); + return; + } + + if (doscan) { + printk(KERN_INFO "scanning ...\n"); + megasas_get_pd_list(instance); + for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) { + for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) { + pd_index = i*MEGASAS_MAX_DEV_PER_CHANNEL + j; + sdev1 = scsi_device_lookup(host, i, j, 0); + if (instance->pd_list[pd_index].driveState == + MR_PD_STATE_SYSTEM) { + if (!sdev1) { + scsi_add_device(host, i, j, 0); + } + if (sdev1) + scsi_device_put(sdev1); + } else { + if (sdev1) { + scsi_remove_device(sdev1); + scsi_device_put(sdev1); + } + } + } + } + + megasas_get_ld_list(instance); + for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { + for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) { + ld_index = + (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; + + sdev1 = scsi_device_lookup(host, + i+MEGASAS_MAX_LD_CHANNELS, j, 0); + if (instance->ld_ids[ld_index] != 0xff) { + if (!sdev1) { + scsi_add_device(host, + i+2, + j, 0); + } else { + scsi_device_put(sdev1); + } + } else { + if (sdev1) { + scsi_remove_device(sdev1); + scsi_device_put(sdev1); + } + } + } + } + } + + if ( instance->aen_cmd != NULL ) { + kfree(ev); + return ; + } + + seq_num = instance->evt_detail->seq_num + 1; + + /* Register AEN with FW for latest sequence number plus 1 */ + class_locale.members.reserved = 0; + class_locale.members.locale = MR_EVT_LOCALE_ALL; + class_locale.members.class = MR_EVT_CLASS_DEBUG; + mutex_lock(&instance->aen_mutex); + error = megasas_register_aen(instance, seq_num, + class_locale.word); + mutex_unlock(&instance->aen_mutex); + + if (error) + printk(KERN_ERR "register aen failed error %x\n", error); + + kfree(ev); +} + + +static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUSR, + megasas_sysfs_show_poll_mode_io, + megasas_sysfs_set_poll_mode_io); + +/** + * megasas_init - Driver load entry point + */ +static int __init megasas_init(void) +{ + int rval; + + /* + * Announce driver version and other information + */ + printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION, + MEGASAS_EXT_VERSION); + + support_poll_for_event = 2; + support_device_change = 1; + + memset(&megasas_mgmt_info, 0, sizeof(megasas_mgmt_info)); + + /* + * Register character device node + */ + rval = register_chrdev(0, "megaraid_sas_ioctl", &megasas_mgmt_fops); + + if (rval < 0) { + printk(KERN_DEBUG "megasas: failed to open device node\n"); + return rval; + } + + megasas_mgmt_majorno = rval; + + /* + * Register ourselves as PCI hotplug module + */ + rval = pci_register_driver(&megasas_pci_driver); + + if (rval) { + printk(KERN_DEBUG "megasas: PCI hotplug regisration failed \n"); + goto err_pcidrv; + } + + rval = driver_create_file(&megasas_pci_driver.driver, + &driver_attr_version); + if (rval) + goto err_dcf_attr_ver; + rval = driver_create_file(&megasas_pci_driver.driver, + &driver_attr_release_date); + if (rval) + goto err_dcf_rel_date; + + rval = driver_create_file(&megasas_pci_driver.driver, + &driver_attr_support_poll_for_event); + if (rval) + goto err_dcf_support_poll_for_event; + + rval = driver_create_file(&megasas_pci_driver.driver, + &driver_attr_dbg_lvl); + if (rval) + goto err_dcf_dbg_lvl; + rval = driver_create_file(&megasas_pci_driver.driver, + &driver_attr_poll_mode_io); + if (rval) + goto err_dcf_poll_mode_io; + + rval = driver_create_file(&megasas_pci_driver.driver, + &driver_attr_support_device_change); + if (rval) + goto err_dcf_support_device_change; + + return rval; + +err_dcf_support_device_change: + driver_remove_file(&megasas_pci_driver.driver, + &driver_attr_poll_mode_io); + +err_dcf_poll_mode_io: + driver_remove_file(&megasas_pci_driver.driver, + &driver_attr_dbg_lvl); +err_dcf_dbg_lvl: + driver_remove_file(&megasas_pci_driver.driver, + &driver_attr_support_poll_for_event); + +err_dcf_support_poll_for_event: + driver_remove_file(&megasas_pci_driver.driver, + &driver_attr_release_date); + +err_dcf_rel_date: + driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version); +err_dcf_attr_ver: + pci_unregister_driver(&megasas_pci_driver); +err_pcidrv: + unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl"); + return rval; +} + +/** + * megasas_exit - Driver unload entry point + */ +static void __exit megasas_exit(void) +{ + driver_remove_file(&megasas_pci_driver.driver, + &driver_attr_poll_mode_io); + driver_remove_file(&megasas_pci_driver.driver, + &driver_attr_dbg_lvl); + driver_remove_file(&megasas_pci_driver.driver, + &driver_attr_support_poll_for_event); + driver_remove_file(&megasas_pci_driver.driver, + &driver_attr_support_device_change); + driver_remove_file(&megasas_pci_driver.driver, + &driver_attr_release_date); + driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version); + + pci_unregister_driver(&megasas_pci_driver); + unregister_chrdev(megasas_mgmt_majorno, "megaraid_sas_ioctl"); +} + +module_init(megasas_init); +module_exit(megasas_exit); -- cgit v1.2.3-59-g8ed1b From 3f1530c1e1f7fc570672f4a54565949070fad05f Mon Sep 17 00:00:00 2001 From: adam radford Date: Tue, 14 Dec 2010 18:51:48 -0800 Subject: [SCSI] megaraid_sas: Update GPL headers. This patch updates the GPL headers in megaraid_sas_base.c and megaraid_sas.h. Signed-off-by: Adam Radford Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_sas.h | 29 +++++++++++++++++------ drivers/scsi/megaraid/megaraid_sas_base.c | 39 ++++++++++++++++++------------- 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index ad16f5e60046..224ec31e5c97 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -1,15 +1,30 @@ /* + * Linux MegaRAID driver for SAS based RAID controllers * - * Linux MegaRAID driver for SAS based RAID controllers + * Copyright (c) 2009-2011 LSI Corporation. * - * Copyright (c) 2003-2005 LSI Corporation. + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * FILE : megaraid_sas.h + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * FILE: megaraid_sas.h + * + * Authors: LSI Corporation + * + * Send feedback to: + * + * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035 + * ATTN: Linuxraid */ #ifndef LSI_MEGARAID_SAS_H diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 427f0f795947..dab29db3b48e 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -1,27 +1,34 @@ /* + * Linux MegaRAID driver for SAS based RAID controllers * - * Linux MegaRAID driver for SAS based RAID controllers + * Copyright (c) 2009-2011 LSI Corporation. * - * Copyright (c) 2003-2005 LSI Corporation. + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * FILE : megaraid_sas.c - * Version : v00.00.04.31-rc1 + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * Authors: - * (email-id : megaraidlinux@lsi.com) - * Sreenivas Bagalkote - * Sumant Patro - * Bo Yang + * FILE: megaraid_sas_base.c + * Version : v00.00.05.29-rc1 * - * List of supported controllers + * Authors: LSI Corporation + * Sreenivas Bagalkote + * Sumant Patro + * Bo Yang * - * OEM Product Name VID DID SSVID SSID - * --- ------------ --- --- ---- ---- + * Send feedback to: + * + * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035 + * ATTN: Linuxraid */ #include -- cgit v1.2.3-59-g8ed1b From e9ccc998b70fbe59626f393bb0328402159c6b5c Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 17 Dec 2010 13:11:16 -0800 Subject: [SCSI] Add missing SPC-4 CDB and MAINTENANCE_[IN,OUT] service action definitions This patch adds a handful of missing CDBs defs that are used by TCM persistent reservation logic in the SPC-4 defined CDB exclusion table for registrations and reservations. This includes a number of missing MI_* and MO_* prefixed service actions defs for MAINTENANCE_IN and MAINTENANCE_OUT that are mentioned wrt to persistent registration and reservation status for the SCSI Initiator Port. Signed-off-by: Nicholas A. Bellinger Signed-off-by: James Bottomley --- include/scsi/scsi.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 216af8538cc9..1651fef18831 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -115,33 +115,61 @@ struct scsi_cmnd; #define PERSISTENT_RESERVE_OUT 0x5f #define VARIABLE_LENGTH_CMD 0x7f #define REPORT_LUNS 0xa0 +#define SECURITY_PROTOCOL_IN 0xa2 #define MAINTENANCE_IN 0xa3 #define MAINTENANCE_OUT 0xa4 #define MOVE_MEDIUM 0xa5 #define EXCHANGE_MEDIUM 0xa6 #define READ_12 0xa8 #define WRITE_12 0xaa +#define READ_MEDIA_SERIAL_NUMBER 0xab #define WRITE_VERIFY_12 0xae #define VERIFY_12 0xaf #define SEARCH_HIGH_12 0xb0 #define SEARCH_EQUAL_12 0xb1 #define SEARCH_LOW_12 0xb2 +#define SECURITY_PROTOCOL_OUT 0xb5 #define READ_ELEMENT_STATUS 0xb8 #define SEND_VOLUME_TAG 0xb6 #define WRITE_LONG_2 0xea +#define EXTENDED_COPY 0x83 +#define RECEIVE_COPY_RESULTS 0x84 +#define ACCESS_CONTROL_IN 0x86 +#define ACCESS_CONTROL_OUT 0x87 #define READ_16 0x88 #define WRITE_16 0x8a +#define READ_ATTRIBUTE 0x8c +#define WRITE_ATTRIBUTE 0x8d #define VERIFY_16 0x8f #define WRITE_SAME_16 0x93 #define SERVICE_ACTION_IN 0x9e /* values for service action in */ #define SAI_READ_CAPACITY_16 0x10 #define SAI_GET_LBA_STATUS 0x12 +/* values for VARIABLE_LENGTH_CMD service action codes + * see spc4r17 Section D.3.5, table D.7 and D.8 */ +#define VLC_SA_RECEIVE_CREDENTIAL 0x1800 /* values for maintenance in */ +#define MI_REPORT_IDENTIFYING_INFORMATION 0x05 #define MI_REPORT_TARGET_PGS 0x0a +#define MI_REPORT_ALIASES 0x0b +#define MI_REPORT_SUPPORTED_OPERATION_CODES 0x0c +#define MI_REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS 0x0d +#define MI_REPORT_PRIORITY 0x0e +#define MI_REPORT_TIMESTAMP 0x0f +#define MI_MANAGEMENT_PROTOCOL_IN 0x10 /* values for maintenance out */ +#define MO_SET_IDENTIFYING_INFORMATION 0x06 #define MO_SET_TARGET_PGS 0x0a +#define MO_CHANGE_ALIASES 0x0b +#define MO_SET_PRIORITY 0x0e +#define MO_SET_TIMESTAMP 0x0f +#define MO_MANAGEMENT_PROTOCOL_OUT 0x10 /* values for variable length command */ +#define XDREAD_32 0x03 +#define XDWRITE_32 0x04 +#define XPWRITE_32 0x06 +#define XDWRITEREAD_32 0x07 #define READ_32 0x09 #define VERIFY_32 0x0a #define WRITE_32 0x0b -- cgit v1.2.3-59-g8ed1b From a8733c7baf457b071528e385a0b7d4aaec79287c Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Fri, 17 Dec 2010 15:36:34 -0500 Subject: [SCSI] fix medium error problems with some arrays which can cause data corruption Our current handling of medium error assumes that data is returned up to the bad sector. This assumption holds good for all disk devices, all DIF arrays and most ordinary arrays. However, an LSI array engine was recently discovered which reports a medium error without returning any data. This means that when we report good data up to the medium error, we've reported junk originally in the buffer as good. Worse, if the read consists of requested data plus a readahead, and the error occurs in readahead, we'll just strip off the readahead and report junk up to userspace as good data with no error. The fix for this is to have the error position computation take into account the amount of data returned by the driver using the scsi residual data. Unfortunately, not every driver fills in this data, but for those who don't, it's set to zero, which means we'll think a full set of data was transferred and the behaviour will be identical to the prior behaviour of the code (believe the buffer up to the error sector). All modern drivers seem to set the residual, so that should fix up the LSI failure/corruption case. Reported-by: Douglas Gilbert Cc: Stable Tree Signed-off-by: James Bottomley --- drivers/scsi/sd.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index d8e2caf9f468..365024b0c407 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1188,6 +1188,12 @@ static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd) u64 end_lba = blk_rq_pos(scmd->request) + (scsi_bufflen(scmd) / 512); u64 bad_lba; int info_valid; + /* + * resid is optional but mostly filled in. When it's unused, + * its value is zero, so we assume the whole buffer transferred + */ + unsigned int transferred = scsi_bufflen(scmd) - scsi_get_resid(scmd); + unsigned int good_bytes; if (scmd->request->cmd_type != REQ_TYPE_FS) return 0; @@ -1221,7 +1227,8 @@ static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd) /* This computation should always be done in terms of * the resolution of the device's medium. */ - return (bad_lba - start_lba) * scmd->device->sector_size; + good_bytes = (bad_lba - start_lba) * scmd->device->sector_size; + return min(good_bytes, transferred); } /** -- cgit v1.2.3-59-g8ed1b From a87e3a67d57472f40da2218793ff6d25c4518498 Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Fri, 17 Dec 2010 19:16:06 -0500 Subject: [SCSI] scsi_debug: set resid to indicate no data-in when medium error set resid to the requested data-in length when a MEDIUM ERROR is simulated. This implies no valid data is returned in the data-in buffer Signed-off-by: Douglas Gilbert Signed-off-by: James Bottomley --- drivers/scsi/scsi_debug.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 2f1f9b079b10..7b310934efed 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -1805,6 +1805,7 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba, devip->sense_buff[5] = (ret >> 8) & 0xff; devip->sense_buff[6] = ret & 0xff; } + scsi_set_resid(SCpnt, scsi_bufflen(SCpnt)); return check_condition_result; } -- cgit v1.2.3-59-g8ed1b From 373daacfce9ea0091cb3027572354ddebefb8ebb Mon Sep 17 00:00:00 2001 From: Kai Makisara Date: Mon, 20 Dec 2010 18:43:39 +0200 Subject: [SCSI] st: Store page order before driver buffer allocation The order of the pages allocated for the driver buffer must be stored before allocation because it is used in freeing already allocated pages if allocation fails. Signed-off-by: Kai Makisara Reported-by: Lukas Kolbe Signed-off-by: James Bottomley --- drivers/scsi/st.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 5b7388f1c835..12a36acae0b0 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -17,7 +17,7 @@ Last modified: 18-JAN-1998 Richard Gooch Devfs support */ -static const char *verstr = "20100829"; +static const char *verstr = "20101219"; #include @@ -3732,6 +3732,7 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm order < ST_MAX_ORDER && b_size < new_size; order++, b_size *= 2) ; /* empty */ + STbuffer->reserved_page_order = order; } if (max_segs * (PAGE_SIZE << order) < new_size) { if (order == ST_MAX_ORDER) @@ -3758,7 +3759,6 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm segs++; } STbuffer->b_data = page_address(STbuffer->reserved_pages[0]); - STbuffer->reserved_page_order = order; return 1; } -- cgit v1.2.3-59-g8ed1b From 46081b166415acb66d4b3150ecefcd9460bb48a1 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Mon, 20 Dec 2010 18:44:45 +0200 Subject: [SCSI] st: Increase success probability in driver buffer allocation Modify allocation to try the minimum possible page order allowed by the HBA scatter/gather segment limit in allocation of the driver's internal buffer. This increases the probability of successful allocation. The allocation may still fail if this minimum order is > 0. Signed-off-by: FUJITA Tomonori Signed-off-by: Kai Makisara Reported-by: Lukas Kolbe Signed-off-by: James Bottomley --- drivers/scsi/st.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 12a36acae0b0..1871b8ae83ae 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -3729,7 +3729,8 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm b_size = PAGE_SIZE << order; } else { for (b_size = PAGE_SIZE, order = 0; - order < ST_MAX_ORDER && b_size < new_size; + order < ST_MAX_ORDER && + max_segs * (PAGE_SIZE << order) < new_size; order++, b_size *= 2) ; /* empty */ STbuffer->reserved_page_order = order; -- cgit v1.2.3-59-g8ed1b From 80d9da98b4034edd31f6bacdb96c7489c4460173 Mon Sep 17 00:00:00 2001 From: adam radford Date: Tue, 21 Dec 2010 10:17:40 -0800 Subject: [SCSI] megaraid_sas: Add MSI-X support and msix_disable module parameter This patch adds MSI-X support and 'msix_disable' module parameter to the megaraid_sas driver. Signed-off-by: Adam Radford Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_sas.h | 3 +++ drivers/scsi/megaraid/megaraid_sas_base.c | 41 +++++++++++++++++++++++++------ 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 224ec31e5c97..ff9845c72a67 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -1335,6 +1335,9 @@ struct megasas_instance { struct timer_list io_completion_timer; struct list_head internal_reset_pending_q; + + u8 msi_flag; + struct msix_entry msixentry; }; enum { diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index dab29db3b48e..2318183f9a67 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -72,6 +72,10 @@ module_param_named(max_sectors, max_sectors, int, 0); MODULE_PARM_DESC(max_sectors, "Maximum number of sectors per IO command"); +static int msix_disable; +module_param(msix_disable, int, S_IRUGO); +MODULE_PARM_DESC(msix_disable, "Disable MSI-X interrupt handling. Default: 0"); + MODULE_LICENSE("GPL"); MODULE_VERSION(MEGASAS_VERSION); MODULE_AUTHOR("megaraidlinux@lsi.com"); @@ -3863,10 +3867,20 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) if (megasas_init_mfi(instance)) goto fail_init_mfi; + /* Try to enable MSI-X */ + if ((instance->pdev->device != PCI_DEVICE_ID_LSI_SAS1078R) && + (instance->pdev->device != PCI_DEVICE_ID_LSI_SAS1078DE) && + (instance->pdev->device != PCI_DEVICE_ID_LSI_VERDE_ZCR) && + !msix_disable && !pci_enable_msix(instance->pdev, + &instance->msixentry, 1)) + instance->msi_flag = 1; + /* * Register IRQ */ - if (request_irq(pdev->irq, megasas_isr, IRQF_SHARED, "megasas", instance)) { + if (request_irq(instance->msi_flag ? instance->msixentry.vector : + pdev->irq, megasas_isr, + IRQF_SHARED, "megasas", instance)) { printk(KERN_DEBUG "megasas: Failed to register IRQ\n"); goto fail_irq; } @@ -3911,8 +3925,10 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_drvdata(pdev, NULL); instance->instancet->disable_intr(instance->reg_set); - free_irq(instance->pdev->irq, instance); - + free_irq(instance->msi_flag ? instance->msixentry.vector : + instance->pdev->irq, instance); + if (instance->msi_flag) + pci_disable_msix(instance->pdev); megasas_release_mfi(instance); fail_irq: @@ -4053,7 +4069,10 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state) pci_set_drvdata(instance->pdev, instance); instance->instancet->disable_intr(instance->reg_set); - free_irq(instance->pdev->irq, instance); + free_irq(instance->msi_flag ? instance->msixentry.vector : + instance->pdev->irq, instance); + if (instance->msi_flag) + pci_disable_msix(instance->pdev); pci_save_state(pdev); pci_disable_device(pdev); @@ -4116,11 +4135,16 @@ megasas_resume(struct pci_dev *pdev) tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc, (unsigned long)instance); + /* Now re-enable MSI-X */ + if (instance->msi_flag) + pci_enable_msix(instance->pdev, &instance->msixentry, 1); + /* * Register IRQ */ - if (request_irq(pdev->irq, megasas_isr, IRQF_SHARED, - "megasas", instance)) { + if (request_irq(instance->msi_flag ? instance->msixentry.vector : + pdev->irq, megasas_isr, + IRQF_SHARED, "megasas", instance)) { printk(KERN_ERR "megasas: Failed to register IRQ\n"); goto fail_irq; } @@ -4218,7 +4242,10 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev) instance->instancet->disable_intr(instance->reg_set); - free_irq(instance->pdev->irq, instance); + free_irq(instance->msi_flag ? instance->msixentry.vector : + instance->pdev->irq, instance); + if (instance->msi_flag) + pci_disable_msix(instance->pdev); megasas_release_mfi(instance); -- cgit v1.2.3-59-g8ed1b From b6d5d8808b4c563a56414a4c4c6d652b5f87c088 Mon Sep 17 00:00:00 2001 From: adam radford Date: Tue, 14 Dec 2010 18:56:07 -0800 Subject: [SCSI] megaraid_sas: Use lowest memory bar for SR-IOV VF support The following patch modifies the megaraid_sas driver to select the lowest memory bar available so the driver will work in SR-IOV VF environments where the memory bar mapping changes. Signed-off-by: Adam Radford Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_sas.h | 1 + drivers/scsi/megaraid/megaraid_sas_base.c | 29 ++++++++++------------------- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index ff9845c72a67..0e09a0ff479d 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -1338,6 +1338,7 @@ struct megasas_instance { u8 msi_flag; struct msix_entry msixentry; + unsigned long bar; }; enum { diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 2318183f9a67..6e7bb7ca9869 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -3236,21 +3236,14 @@ static int megasas_init_mfi(struct megasas_instance *instance) u32 tmp_sectors; struct megasas_register_set __iomem *reg_set; struct megasas_ctrl_info *ctrl_info; - /* - * Map the message registers - */ - if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078GEN2) || - (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) || - (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || - (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0079GEN2)) { - instance->base_addr = pci_resource_start(instance->pdev, 1); - } else { - instance->base_addr = pci_resource_start(instance->pdev, 0); - } - - if (pci_request_selected_regions(instance->pdev, - pci_select_bars(instance->pdev, IORESOURCE_MEM), - "megasas: LSI")) { + unsigned long bar_list; + + /* Find first memory bar */ + bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM); + instance->bar = find_first_bit(&bar_list, sizeof(unsigned long)); + instance->base_addr = pci_resource_start(instance->pdev, instance->bar); + if (pci_request_selected_regions(instance->pdev, instance->bar, + "megasas: LSI")) { printk(KERN_DEBUG "megasas: IO memory region busy!\n"); return -EBUSY; } @@ -3411,8 +3404,7 @@ static int megasas_init_mfi(struct megasas_instance *instance) iounmap(instance->reg_set); fail_ioremap: - pci_release_selected_regions(instance->pdev, - pci_select_bars(instance->pdev, IORESOURCE_MEM)); + pci_release_selected_regions(instance->pdev, instance->bar); return -EINVAL; } @@ -3432,8 +3424,7 @@ static void megasas_release_mfi(struct megasas_instance *instance) iounmap(instance->reg_set); - pci_release_selected_regions(instance->pdev, - pci_select_bars(instance->pdev, IORESOURCE_MEM)); + pci_release_selected_regions(instance->pdev, instance->bar); } /** -- cgit v1.2.3-59-g8ed1b From cd50ba8ede5cd3c4606a8e5d163913da5ff36ad7 Mon Sep 17 00:00:00 2001 From: adam radford Date: Tue, 21 Dec 2010 10:23:23 -0800 Subject: [SCSI] megaraid_sas: Add struct megasas_instance_template changes The following patch adds struct megasas_instance_template changes to the megaraid_sas driver, and changes all code to use the new instance entries: irqreturn_t (*service_isr )(int irq, void *devp); void (*tasklet)(unsigned long); u32 (*init_adapter)(struct megasas_instance *); u32 (*build_and_issue_cmd) (struct megasas_instance *, struct scsi_cmnd *); void (*issue_dcmd) (struct megasas_instance *instance, struct megasas_cmd *cmd); Signed-off-by: Adam Radford Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_sas.h | 7 + drivers/scsi/megaraid/megaraid_sas_base.c | 278 +++++++++++++++++++----------- 2 files changed, 180 insertions(+), 105 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 0e09a0ff479d..a0b8ee1a5d2d 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -1364,6 +1364,13 @@ struct megasas_instance_template { struct megasas_register_set __iomem *); int (*check_reset)(struct megasas_instance *, \ struct megasas_register_set __iomem *); + irqreturn_t (*service_isr)(int irq, void *devp); + void (*tasklet)(unsigned long); + u32 (*init_adapter)(struct megasas_instance *); + u32 (*build_and_issue_cmd) (struct megasas_instance *, + struct scsi_cmnd *); + void (*issue_dcmd) (struct megasas_instance *instance, + struct megasas_cmd *cmd); }; #define MEGASAS_IS_LOGICAL(scp) \ diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 6e7bb7ca9869..5938267e472b 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -131,6 +131,20 @@ spinlock_t poll_aen_lock; static void megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, u8 alt_status); +static irqreturn_t megasas_isr(int irq, void *devp); +static u32 +megasas_init_adapter_mfi(struct megasas_instance *instance); +u32 +megasas_build_and_issue_cmd(struct megasas_instance *instance, + struct scsi_cmnd *scmd); +static void megasas_complete_cmd_dpc(unsigned long instance_addr); + +void +megasas_issue_dcmd(struct megasas_instance *instance, struct megasas_cmd *cmd) +{ + instance->instancet->fire_cmd(instance, + cmd->frame_phys_addr, 0, instance->reg_set); +} /** * megasas_get_cmd - Get a command from the free pool @@ -334,6 +348,11 @@ static struct megasas_instance_template megasas_instance_template_xscale = { .read_fw_status_reg = megasas_read_fw_status_reg_xscale, .adp_reset = megasas_adp_reset_xscale, .check_reset = megasas_check_reset_xscale, + .service_isr = megasas_isr, + .tasklet = megasas_complete_cmd_dpc, + .init_adapter = megasas_init_adapter_mfi, + .build_and_issue_cmd = megasas_build_and_issue_cmd, + .issue_dcmd = megasas_issue_dcmd, }; /** @@ -460,6 +479,11 @@ static struct megasas_instance_template megasas_instance_template_ppc = { .read_fw_status_reg = megasas_read_fw_status_reg_ppc, .adp_reset = megasas_adp_reset_ppc, .check_reset = megasas_check_reset_ppc, + .service_isr = megasas_isr, + .tasklet = megasas_complete_cmd_dpc, + .init_adapter = megasas_init_adapter_mfi, + .build_and_issue_cmd = megasas_build_and_issue_cmd, + .issue_dcmd = megasas_issue_dcmd, }; /** @@ -581,6 +605,11 @@ static struct megasas_instance_template megasas_instance_template_skinny = { .read_fw_status_reg = megasas_read_fw_status_reg_skinny, .adp_reset = megasas_adp_reset_skinny, .check_reset = megasas_check_reset_skinny, + .service_isr = megasas_isr, + .tasklet = megasas_complete_cmd_dpc, + .init_adapter = megasas_init_adapter_mfi, + .build_and_issue_cmd = megasas_build_and_issue_cmd, + .issue_dcmd = megasas_issue_dcmd, }; @@ -755,6 +784,11 @@ static struct megasas_instance_template megasas_instance_template_gen2 = { .read_fw_status_reg = megasas_read_fw_status_reg_gen2, .adp_reset = megasas_adp_reset_gen2, .check_reset = megasas_check_reset_gen2, + .service_isr = megasas_isr, + .tasklet = megasas_complete_cmd_dpc, + .init_adapter = megasas_init_adapter_mfi, + .build_and_issue_cmd = megasas_build_and_issue_cmd, + .issue_dcmd = megasas_issue_dcmd, }; /** @@ -1339,6 +1373,51 @@ megasas_dump_pending_frames(struct megasas_instance *instance) printk(KERN_ERR "megasas[%d]: Dumping Done.\n\n",instance->host->host_no); } +u32 +megasas_build_and_issue_cmd(struct megasas_instance *instance, + struct scsi_cmnd *scmd) +{ + struct megasas_cmd *cmd; + u32 frame_count; + + cmd = megasas_get_cmd(instance); + if (!cmd) + return SCSI_MLQUEUE_HOST_BUSY; + + /* + * Logical drive command + */ + if (megasas_is_ldio(scmd)) + frame_count = megasas_build_ldio(instance, scmd, cmd); + else + frame_count = megasas_build_dcdb(instance, scmd, cmd); + + if (!frame_count) + goto out_return_cmd; + + cmd->scmd = scmd; + scmd->SCp.ptr = (char *)cmd; + + /* + * Issue the command to the FW + */ + atomic_inc(&instance->fw_outstanding); + + instance->instancet->fire_cmd(instance, cmd->frame_phys_addr, + cmd->frame_count-1, instance->reg_set); + /* + * Check if we have pend cmds to be completed + */ + if (poll_mode_io && atomic_read(&instance->fw_outstanding)) + tasklet_schedule(&instance->isr_tasklet); + + return 0; +out_return_cmd: + megasas_return_cmd(instance, cmd); + return 1; +} + + /** * megasas_queue_command - Queue entry point * @scmd: SCSI command to be queued @@ -1347,8 +1426,6 @@ megasas_dump_pending_frames(struct megasas_instance *instance) static int megasas_queue_command_lck(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *)) { - u32 frame_count; - struct megasas_cmd *cmd; struct megasas_instance *instance; unsigned long flags; @@ -1387,42 +1464,13 @@ megasas_queue_command_lck(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd break; } - cmd = megasas_get_cmd(instance); - if (!cmd) + if (instance->instancet->build_and_issue_cmd(instance, scmd)) { + printk(KERN_ERR "megasas: Err returned from build_and_issue_cmd\n"); return SCSI_MLQUEUE_HOST_BUSY; - - /* - * Logical drive command - */ - if (megasas_is_ldio(scmd)) - frame_count = megasas_build_ldio(instance, scmd, cmd); - else - frame_count = megasas_build_dcdb(instance, scmd, cmd); - - if (!frame_count) - goto out_return_cmd; - - cmd->scmd = scmd; - scmd->SCp.ptr = (char *)cmd; - - /* - * Issue the command to the FW - */ - atomic_inc(&instance->fw_outstanding); - - instance->instancet->fire_cmd(instance, cmd->frame_phys_addr, - cmd->frame_count-1, instance->reg_set); - /* - * Check if we have pend cmds to be completed - */ - if (poll_mode_io && atomic_read(&instance->fw_outstanding)) - tasklet_schedule(&instance->isr_tasklet); - + } return 0; - out_return_cmd: - megasas_return_cmd(instance, cmd); out_done: done(scmd); return 0; @@ -3221,69 +3269,15 @@ megasas_io_completion_timer(unsigned long instance_addr) jiffies + MEGASAS_COMPLETION_TIMER_INTERVAL); } -/** - * megasas_init_mfi - Initializes the FW - * @instance: Adapter soft state - * - * This is the main function for initializing MFI firmware. - */ -static int megasas_init_mfi(struct megasas_instance *instance) +static u32 +megasas_init_adapter_mfi(struct megasas_instance *instance) { + struct megasas_register_set __iomem *reg_set; u32 context_sz; u32 reply_q_sz; - u32 max_sectors_1; - u32 max_sectors_2; - u32 tmp_sectors; - struct megasas_register_set __iomem *reg_set; - struct megasas_ctrl_info *ctrl_info; - unsigned long bar_list; - - /* Find first memory bar */ - bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM); - instance->bar = find_first_bit(&bar_list, sizeof(unsigned long)); - instance->base_addr = pci_resource_start(instance->pdev, instance->bar); - if (pci_request_selected_regions(instance->pdev, instance->bar, - "megasas: LSI")) { - printk(KERN_DEBUG "megasas: IO memory region busy!\n"); - return -EBUSY; - } - - instance->reg_set = ioremap_nocache(instance->base_addr, 8192); - - if (!instance->reg_set) { - printk(KERN_DEBUG "megasas: Failed to map IO mem\n"); - goto fail_ioremap; - } reg_set = instance->reg_set; - switch(instance->pdev->device) - { - case PCI_DEVICE_ID_LSI_SAS1078R: - case PCI_DEVICE_ID_LSI_SAS1078DE: - instance->instancet = &megasas_instance_template_ppc; - break; - case PCI_DEVICE_ID_LSI_SAS1078GEN2: - case PCI_DEVICE_ID_LSI_SAS0079GEN2: - instance->instancet = &megasas_instance_template_gen2; - break; - case PCI_DEVICE_ID_LSI_SAS0073SKINNY: - case PCI_DEVICE_ID_LSI_SAS0071SKINNY: - instance->instancet = &megasas_instance_template_skinny; - break; - case PCI_DEVICE_ID_LSI_SAS1064R: - case PCI_DEVICE_ID_DELL_PERC5: - default: - instance->instancet = &megasas_instance_template_xscale; - break; - } - - /* - * We expect the FW state to be READY - */ - if (megasas_transition_to_ready(instance)) - goto fail_ready_state; - /* * Get various operational parameters from status register */ @@ -3337,6 +3331,87 @@ static int megasas_init_mfi(struct megasas_instance *instance) if (instance->fw_support_ieee) instance->flag_ieee = 1; + return 0; + +fail_fw_init: + + pci_free_consistent(instance->pdev, reply_q_sz, + instance->reply_queue, instance->reply_queue_h); +fail_reply_queue: + megasas_free_cmds(instance); + +fail_alloc_cmds: + iounmap(instance->reg_set); + return 1; +} + +/** + * megasas_init_fw - Initializes the FW + * @instance: Adapter soft state + * + * This is the main function for initializing firmware + */ + +static int megasas_init_fw(struct megasas_instance *instance) +{ + u32 max_sectors_1; + u32 max_sectors_2; + u32 tmp_sectors; + struct megasas_register_set __iomem *reg_set; + struct megasas_ctrl_info *ctrl_info; + unsigned long bar_list; + + /* Find first memory bar */ + bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM); + instance->bar = find_first_bit(&bar_list, sizeof(unsigned long)); + instance->base_addr = pci_resource_start(instance->pdev, instance->bar); + if (pci_request_selected_regions(instance->pdev, instance->bar, + "megasas: LSI")) { + printk(KERN_DEBUG "megasas: IO memory region busy!\n"); + return -EBUSY; + } + + instance->reg_set = ioremap_nocache(instance->base_addr, 8192); + + if (!instance->reg_set) { + printk(KERN_DEBUG "megasas: Failed to map IO mem\n"); + goto fail_ioremap; + } + + reg_set = instance->reg_set; + + switch (instance->pdev->device) { + case PCI_DEVICE_ID_LSI_SAS1078R: + case PCI_DEVICE_ID_LSI_SAS1078DE: + instance->instancet = &megasas_instance_template_ppc; + break; + case PCI_DEVICE_ID_LSI_SAS1078GEN2: + case PCI_DEVICE_ID_LSI_SAS0079GEN2: + instance->instancet = &megasas_instance_template_gen2; + break; + case PCI_DEVICE_ID_LSI_SAS0073SKINNY: + case PCI_DEVICE_ID_LSI_SAS0071SKINNY: + instance->instancet = &megasas_instance_template_skinny; + break; + case PCI_DEVICE_ID_LSI_SAS1064R: + case PCI_DEVICE_ID_DELL_PERC5: + default: + instance->instancet = &megasas_instance_template_xscale; + break; + } + + /* + * We expect the FW state to be READY + */ + if (megasas_transition_to_ready(instance)) + goto fail_ready_state; + + /* Get operational params, sge flags, send init cmd to controller */ + if (instance->instancet->init_adapter(instance)) + return -ENODEV; + + printk(KERN_ERR "megasas: INIT adapter done\n"); + /** for passthrough * the following function will get the PD LIST. */ @@ -3392,15 +3467,7 @@ static int megasas_init_mfi(struct megasas_instance *instance) MEGASAS_COMPLETION_TIMER_INTERVAL); return 0; - fail_fw_init: - - pci_free_consistent(instance->pdev, reply_q_sz, - instance->reply_queue, instance->reply_queue_h); - fail_reply_queue: - megasas_free_cmds(instance); - - fail_alloc_cmds: - fail_ready_state: +fail_ready_state: iounmap(instance->reg_set); fail_ioremap: @@ -3855,7 +3922,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) /* * Initialize MFI Firmware */ - if (megasas_init_mfi(instance)) + if (megasas_init_fw(instance)) goto fail_init_mfi; /* Try to enable MSI-X */ @@ -3870,7 +3937,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) * Register IRQ */ if (request_irq(instance->msi_flag ? instance->msixentry.vector : - pdev->irq, megasas_isr, + pdev->irq, instance->instancet->service_isr, IRQF_SHARED, "megasas", instance)) { printk(KERN_DEBUG "megasas: Failed to register IRQ\n"); goto fail_irq; @@ -3920,7 +3987,6 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) instance->pdev->irq, instance); if (instance->msi_flag) pci_disable_msix(instance->pdev); - megasas_release_mfi(instance); fail_irq: fail_init_mfi: @@ -3930,9 +3996,11 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) instance->evt_detail, instance->evt_detail_h); - if (instance->producer) + if (instance->producer) { pci_free_consistent(pdev, sizeof(u32), instance->producer, instance->producer_h); + megasas_release_mfi(instance); + } if (instance->consumer) pci_free_consistent(pdev, sizeof(u32), instance->consumer, instance->consumer_h); @@ -4134,7 +4202,7 @@ megasas_resume(struct pci_dev *pdev) * Register IRQ */ if (request_irq(instance->msi_flag ? instance->msixentry.vector : - pdev->irq, megasas_isr, + pdev->irq, instance->instancet->service_isr, IRQF_SHARED, "megasas", instance)) { printk(KERN_ERR "megasas: Failed to register IRQ\n"); goto fail_irq; -- cgit v1.2.3-59-g8ed1b From 9c915a8c99bce637226aa09cb05fc18486b229cb Mon Sep 17 00:00:00 2001 From: adam radford Date: Tue, 21 Dec 2010 13:34:31 -0800 Subject: [SCSI] megaraid_sas: Add 9565/9285 specific code This patch adds MegaRAID 9265/9285 (Device id 0x5b) specific code Signed-off-by: Adam Radford Signed-off-by: James Bottomley --- drivers/scsi/megaraid/Makefile | 3 +- drivers/scsi/megaraid/megaraid_sas.h | 38 +- drivers/scsi/megaraid/megaraid_sas_base.c | 362 +++-- drivers/scsi/megaraid/megaraid_sas_fp.c | 516 ++++++ drivers/scsi/megaraid/megaraid_sas_fusion.c | 2248 +++++++++++++++++++++++++++ drivers/scsi/megaraid/megaraid_sas_fusion.h | 695 +++++++++ 6 files changed, 3751 insertions(+), 111 deletions(-) create mode 100644 drivers/scsi/megaraid/megaraid_sas_fp.c create mode 100644 drivers/scsi/megaraid/megaraid_sas_fusion.c create mode 100644 drivers/scsi/megaraid/megaraid_sas_fusion.h diff --git a/drivers/scsi/megaraid/Makefile b/drivers/scsi/megaraid/Makefile index 6613a2ceea03..5826ed509e3e 100644 --- a/drivers/scsi/megaraid/Makefile +++ b/drivers/scsi/megaraid/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_MEGARAID_MM) += megaraid_mm.o obj-$(CONFIG_MEGARAID_MAILBOX) += megaraid_mbox.o obj-$(CONFIG_MEGARAID_SAS) += megaraid_sas.o -megaraid_sas-objs := megaraid_sas_base.o +megaraid_sas-objs := megaraid_sas_base.o megaraid_sas_fusion.o \ + megaraid_sas_fp.o diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index a0b8ee1a5d2d..1b5e375732c0 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -33,9 +33,9 @@ /* * MegaRAID SAS Driver meta data */ -#define MEGASAS_VERSION "00.00.04.31-rc1" -#define MEGASAS_RELDATE "May 3, 2010" -#define MEGASAS_EXT_VERSION "Mon. May 3, 11:41:51 PST 2010" +#define MEGASAS_VERSION "00.00.05.29-rc1" +#define MEGASAS_RELDATE "Dec. 7, 2010" +#define MEGASAS_EXT_VERSION "Tue. Dec. 7 17:00:00 PDT 2010" /* * Device IDs @@ -47,6 +47,7 @@ #define PCI_DEVICE_ID_LSI_SAS0079GEN2 0x0079 #define PCI_DEVICE_ID_LSI_SAS0073SKINNY 0x0073 #define PCI_DEVICE_ID_LSI_SAS0071SKINNY 0x0071 +#define PCI_DEVICE_ID_LSI_FUSION 0x005b /* * ===================================== @@ -436,7 +437,6 @@ struct megasas_ctrl_prop { * Add properties that can be controlled by * a bit in the following structure. */ - struct { u32 copyBackDisabled : 1; u32 SMARTerEnabled : 1; @@ -716,6 +716,7 @@ struct megasas_ctrl_info { #define MEGASAS_DEFAULT_INIT_ID -1 #define MEGASAS_MAX_LUN 8 #define MEGASAS_MAX_LD 64 +#define MEGASAS_DEFAULT_CMD_PER_LUN 128 #define MEGASAS_MAX_PD (MEGASAS_MAX_PD_CHANNELS * \ MEGASAS_MAX_DEV_PER_CHANNEL) #define MEGASAS_MAX_LD_IDS (MEGASAS_MAX_LD_CHANNELS * \ @@ -784,7 +785,10 @@ struct megasas_ctrl_info { */ struct megasas_register_set { - u32 reserved_0[4]; /*0000h*/ + u32 doorbell; /*0000h*/ + u32 fusion_seq_offset; /*0004h*/ + u32 fusion_host_diag; /*0008h*/ + u32 reserved_01; /*000Ch*/ u32 inbound_msg_0; /*0010h*/ u32 inbound_msg_1; /*0014h*/ @@ -804,15 +808,18 @@ struct megasas_register_set { u32 inbound_queue_port; /*0040h*/ u32 outbound_queue_port; /*0044h*/ - u32 reserved_2[22]; /*0048h*/ + u32 reserved_2[9]; /*0048h*/ + u32 reply_post_host_index; /*006Ch*/ + u32 reserved_2_2[12]; /*0070h*/ u32 outbound_doorbell_clear; /*00A0h*/ u32 reserved_3[3]; /*00A4h*/ u32 outbound_scratch_pad ; /*00B0h*/ + u32 outbound_scratch_pad_2; /*00B4h*/ - u32 reserved_4[3]; /*00B4h*/ + u32 reserved_4[2]; /*00B8h*/ u32 inbound_low_queue_port ; /*00C0h*/ @@ -1287,6 +1294,9 @@ struct megasas_instance { u16 max_num_sge; u16 max_fw_cmds; + /* For Fusion its num IOCTL cmds, for others MFI based its + max_fw_cmds */ + u16 max_mfi_cmds; u32 max_sectors_per_req; struct megasas_aen_event *ev; @@ -1336,9 +1346,15 @@ struct megasas_instance { struct timer_list io_completion_timer; struct list_head internal_reset_pending_q; + /* Ptr to hba specfic information */ + void *ctrl_context; u8 msi_flag; struct msix_entry msixentry; + u64 map_id; + struct megasas_cmd *map_update_cmd; unsigned long bar; + long reset_flags; + struct mutex reset_mutex; }; enum { @@ -1397,7 +1413,13 @@ struct megasas_cmd { struct list_head list; struct scsi_cmnd *scmd; struct megasas_instance *instance; - u32 frame_count; + union { + struct { + u16 smid; + u16 resvd; + } context; + u32 frame_count; + }; }; #define MAX_MGMT_ADAPTERS 1024 diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 5938267e472b..5d6d07bd1cd0 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -53,6 +53,7 @@ #include #include #include +#include "megaraid_sas_fusion.h" #include "megaraid_sas.h" /* @@ -81,7 +82,7 @@ MODULE_VERSION(MEGASAS_VERSION); MODULE_AUTHOR("megaraidlinux@lsi.com"); MODULE_DESCRIPTION("LSI MegaRAID SAS Driver"); -static int megasas_transition_to_ready(struct megasas_instance *instance); +int megasas_transition_to_ready(struct megasas_instance *instance); static int megasas_get_pd_list(struct megasas_instance *instance); static int megasas_issue_init_mfi(struct megasas_instance *instance); static int megasas_register_aen(struct megasas_instance *instance, @@ -109,6 +110,8 @@ static struct pci_device_id megasas_pci_table[] = { /* xscale IOP, vega */ {PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)}, /* xscale IOP */ + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FUSION)}, + /* Fusion */ {} }; @@ -122,15 +125,16 @@ static DEFINE_MUTEX(megasas_async_queue_mutex); static int megasas_poll_wait_aen; static DECLARE_WAIT_QUEUE_HEAD(megasas_poll_wait); static u32 support_poll_for_event; -static u32 megasas_dbg_lvl; +u32 megasas_dbg_lvl; static u32 support_device_change; /* define lock for aen poll */ spinlock_t poll_aen_lock; -static void +void megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, u8 alt_status); + static irqreturn_t megasas_isr(int irq, void *devp); static u32 megasas_init_adapter_mfi(struct megasas_instance *instance); @@ -138,6 +142,23 @@ u32 megasas_build_and_issue_cmd(struct megasas_instance *instance, struct scsi_cmnd *scmd); static void megasas_complete_cmd_dpc(unsigned long instance_addr); +void +megasas_release_fusion(struct megasas_instance *instance); +int +megasas_ioc_init_fusion(struct megasas_instance *instance); +void +megasas_free_cmds_fusion(struct megasas_instance *instance); +u8 +megasas_get_map_info(struct megasas_instance *instance); +int +megasas_sync_map_info(struct megasas_instance *instance); +int +wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd); +void megasas_reset_reply_desc(struct megasas_instance *instance); +u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map, + struct LD_LOAD_BALANCE_INFO *lbInfo); +int megasas_reset_fusion(struct Scsi_Host *shost); +void megasas_fusion_ocr_wq(struct work_struct *work); void megasas_issue_dcmd(struct megasas_instance *instance, struct megasas_cmd *cmd) @@ -152,7 +173,7 @@ megasas_issue_dcmd(struct megasas_instance *instance, struct megasas_cmd *cmd) * * Returns a free command from the pool */ -static struct megasas_cmd *megasas_get_cmd(struct megasas_instance +struct megasas_cmd *megasas_get_cmd(struct megasas_instance *instance) { unsigned long flags; @@ -177,7 +198,7 @@ static struct megasas_cmd *megasas_get_cmd(struct megasas_instance * @instance: Adapter soft state * @cmd: Command packet to be returned to free command pool */ -static inline void +inline void megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) { unsigned long flags; @@ -185,6 +206,7 @@ megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) spin_lock_irqsave(&instance->cmd_pool_lock, flags); cmd->scmd = NULL; + cmd->frame_count = 0; list_add_tail(&cmd->list, &instance->cmd_pool); spin_unlock_irqrestore(&instance->cmd_pool_lock, flags); @@ -796,6 +818,11 @@ static struct megasas_instance_template megasas_instance_template_gen2 = { * specific to gen2 (deviceid : 0x78, 0x79) controllers */ +/* + * Template added for TB (Fusion) + */ +extern struct megasas_instance_template megasas_instance_template_fusion; + /** * megasas_issue_polled - Issues a polling command * @instance: Adapter soft state @@ -803,11 +830,9 @@ static struct megasas_instance_template megasas_instance_template_gen2 = { * * For polling, MFI requires the cmd_status to be set to 0xFF before posting. */ -static int +int megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd) { - int i; - u32 msecs = MFI_POLL_TIMEOUT_SECS * 1000; struct megasas_header *frame_hdr = &cmd->frame->hdr; @@ -817,21 +842,12 @@ megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd) /* * Issue the frame using inbound queue port */ - instance->instancet->fire_cmd(instance, - cmd->frame_phys_addr, 0, instance->reg_set); + instance->instancet->issue_dcmd(instance, cmd); /* * Wait for cmd_status to change */ - for (i = 0; (i < msecs) && (frame_hdr->cmd_status == 0xff); i++) { - rmb(); - msleep(1); - } - - if (frame_hdr->cmd_status == 0xff) - return -ETIME; - - return 0; + return wait_and_poll(instance, cmd); } /** @@ -849,8 +865,7 @@ megasas_issue_blocked_cmd(struct megasas_instance *instance, { cmd->cmd_status = ENODATA; - instance->instancet->fire_cmd(instance, - cmd->frame_phys_addr, 0, instance->reg_set); + instance->instancet->issue_dcmd(instance, cmd); wait_event(instance->int_cmd_wait_q, cmd->cmd_status != ENODATA); @@ -894,8 +909,7 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, cmd->sync_cmd = 1; cmd->cmd_status = 0xFF; - instance->instancet->fire_cmd(instance, - cmd->frame_phys_addr, 0, instance->reg_set); + instance->instancet->issue_dcmd(instance, cmd); /* * Wait for this cmd to complete @@ -1291,7 +1305,7 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, * Called by megasas_queue_command to find out if the command to be queued * is a logical drive command */ -static inline int megasas_is_ldio(struct scsi_cmnd *cmd) +inline int megasas_is_ldio(struct scsi_cmnd *cmd) { if (!MEGASAS_IS_LOGICAL(cmd)) return 0; @@ -1551,15 +1565,44 @@ static int megasas_slave_alloc(struct scsi_device *sdev) return 0; } -static void megaraid_sas_kill_hba(struct megasas_instance *instance) +void megaraid_sas_kill_hba(struct megasas_instance *instance) { if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || - (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { - writel(MFI_STOP_ADP, - &instance->reg_set->reserved_0[0]); + (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) || + (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION)) { + writel(MFI_STOP_ADP, &instance->reg_set->doorbell); } else { - writel(MFI_STOP_ADP, - &instance->reg_set->inbound_doorbell); + writel(MFI_STOP_ADP, &instance->reg_set->inbound_doorbell); + } +} + + /** + * megasas_check_and_restore_queue_depth - Check if queue depth needs to be + * restored to max value + * @instance: Adapter soft state + * + */ +void +megasas_check_and_restore_queue_depth(struct megasas_instance *instance) +{ + unsigned long flags; + if (instance->flag & MEGASAS_FW_BUSY + && time_after(jiffies, instance->last_time + 5 * HZ) + && atomic_read(&instance->fw_outstanding) < 17) { + + spin_lock_irqsave(instance->host->host_lock, flags); + instance->flag &= ~MEGASAS_FW_BUSY; + if ((instance->pdev->device == + PCI_DEVICE_ID_LSI_SAS0073SKINNY) || + (instance->pdev->device == + PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { + instance->host->can_queue = + instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS; + } else + instance->host->can_queue = + instance->max_fw_cmds - MEGASAS_INT_CMDS; + + spin_unlock_irqrestore(instance->host->host_lock, flags); } } @@ -1613,24 +1656,7 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr) /* * Check if we can restore can_queue */ - if (instance->flag & MEGASAS_FW_BUSY - && time_after(jiffies, instance->last_time + 5 * HZ) - && atomic_read(&instance->fw_outstanding) < 17) { - - spin_lock_irqsave(instance->host->host_lock, flags); - instance->flag &= ~MEGASAS_FW_BUSY; - if ((instance->pdev->device == - PCI_DEVICE_ID_LSI_SAS0073SKINNY) || - (instance->pdev->device == - PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { - instance->host->can_queue = - instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS; - } else - instance->host->can_queue = - instance->max_fw_cmds - MEGASAS_INT_CMDS; - - spin_unlock_irqrestore(instance->host->host_lock, flags); - } + megasas_check_and_restore_queue_depth(instance); } static void @@ -1808,7 +1834,7 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance) (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { writel(MFI_STOP_ADP, - &instance->reg_set->reserved_0[0]); + &instance->reg_set->doorbell); } else { writel(MFI_STOP_ADP, &instance->reg_set->inbound_doorbell); @@ -1912,11 +1938,16 @@ static int megasas_reset_device(struct scsi_cmnd *scmd) static int megasas_reset_bus_host(struct scsi_cmnd *scmd) { int ret; + struct megasas_instance *instance; + instance = (struct megasas_instance *)scmd->device->host->hostdata; /* * First wait for all commands to complete */ - ret = megasas_generic_reset(scmd); + if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) + ret = megasas_reset_fusion(scmd->device->host); + else + ret = megasas_generic_reset(scmd); return ret; } @@ -2086,13 +2117,14 @@ megasas_complete_abort(struct megasas_instance *instance, * an alternate status (as in the case of aborted * commands) */ -static void +void megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, u8 alt_status) { int exception = 0; struct megasas_header *hdr = &cmd->frame->hdr; unsigned long flags; + struct fusion_context *fusion = instance->ctrl_context; /* flag for the retry reset */ cmd->retry_for_fw_reset = 0; @@ -2185,6 +2217,37 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, case MFI_CMD_SMP: case MFI_CMD_STP: case MFI_CMD_DCMD: + /* Check for LD map update */ + if ((cmd->frame->dcmd.opcode == MR_DCMD_LD_MAP_GET_INFO) && + (cmd->frame->dcmd.mbox.b[1] == 1)) { + spin_lock_irqsave(instance->host->host_lock, flags); + if (cmd->frame->hdr.cmd_status != 0) { + if (cmd->frame->hdr.cmd_status != + MFI_STAT_NOT_FOUND) + printk(KERN_WARNING "megasas: map sync" + "failed, status = 0x%x.\n", + cmd->frame->hdr.cmd_status); + else { + megasas_return_cmd(instance, cmd); + spin_unlock_irqrestore( + instance->host->host_lock, + flags); + break; + } + } else + instance->map_id++; + megasas_return_cmd(instance, cmd); + if (MR_ValidateMapInfo( + fusion->ld_map[(instance->map_id & 1)], + fusion->load_balance_info)) + fusion->fast_path_io = 1; + else + fusion->fast_path_io = 0; + megasas_sync_map_info(instance); + spin_unlock_irqrestore(instance->host->host_lock, + flags); + break; + } if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET_INFO || cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET) { spin_lock_irqsave(&poll_aen_lock, flags); @@ -2523,7 +2586,7 @@ static irqreturn_t megasas_isr(int irq, void *devp) * states, driver must take steps to bring it to ready state. Otherwise, it * has to wait for the ready state. */ -static int +int megasas_transition_to_ready(struct megasas_instance* instance) { int i; @@ -2557,11 +2620,12 @@ megasas_transition_to_ready(struct megasas_instance* instance) if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || (instance->pdev->device == - PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { - + PCI_DEVICE_ID_LSI_SAS0071SKINNY) || + (instance->pdev->device == + PCI_DEVICE_ID_LSI_FUSION)) { writel( MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG, - &instance->reg_set->reserved_0[0]); + &instance->reg_set->doorbell); } else { writel( MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG, @@ -2574,11 +2638,13 @@ megasas_transition_to_ready(struct megasas_instance* instance) case MFI_STATE_BOOT_MESSAGE_PENDING: if ((instance->pdev->device == - PCI_DEVICE_ID_LSI_SAS0073SKINNY) || - (instance->pdev->device == - PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { + PCI_DEVICE_ID_LSI_SAS0073SKINNY) || + (instance->pdev->device == + PCI_DEVICE_ID_LSI_SAS0071SKINNY) || + (instance->pdev->device == + PCI_DEVICE_ID_LSI_FUSION)) { writel(MFI_INIT_HOTPLUG, - &instance->reg_set->reserved_0[0]); + &instance->reg_set->doorbell); } else writel(MFI_INIT_HOTPLUG, &instance->reg_set->inbound_doorbell); @@ -2595,9 +2661,23 @@ megasas_transition_to_ready(struct megasas_instance* instance) if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || (instance->pdev->device == - PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { + PCI_DEVICE_ID_LSI_SAS0071SKINNY) || + (instance->pdev->device + == PCI_DEVICE_ID_LSI_FUSION)) { writel(MFI_RESET_FLAGS, - &instance->reg_set->reserved_0[0]); + &instance->reg_set->doorbell); + if (instance->pdev->device == + PCI_DEVICE_ID_LSI_FUSION) { + for (i = 0; i < (10 * 1000); i += 20) { + if (readl( + &instance-> + reg_set-> + doorbell) & 1) + msleep(20); + else + break; + } + } } else writel(MFI_RESET_FLAGS, &instance->reg_set->inbound_doorbell); @@ -2681,7 +2761,7 @@ megasas_transition_to_ready(struct megasas_instance* instance) static void megasas_teardown_frame_pool(struct megasas_instance *instance) { int i; - u32 max_cmd = instance->max_fw_cmds; + u32 max_cmd = instance->max_mfi_cmds; struct megasas_cmd *cmd; if (!instance->frame_dma_pool) @@ -2732,7 +2812,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance) u32 frame_count; struct megasas_cmd *cmd; - max_cmd = instance->max_fw_cmds; + max_cmd = instance->max_mfi_cmds; /* * Size of our frame is 64 bytes for MFI frame, followed by max SG @@ -2819,14 +2899,15 @@ static int megasas_create_frame_pool(struct megasas_instance *instance) * megasas_free_cmds - Free all the cmds in the free cmd pool * @instance: Adapter soft state */ -static void megasas_free_cmds(struct megasas_instance *instance) +void megasas_free_cmds(struct megasas_instance *instance) { int i; /* First free the MFI frame pool */ megasas_teardown_frame_pool(instance); /* Free all the commands in the cmd_list */ - for (i = 0; i < instance->max_fw_cmds; i++) + for (i = 0; i < instance->max_mfi_cmds; i++) + kfree(instance->cmd_list[i]); /* Free the cmd_list buffer itself */ @@ -2854,14 +2935,14 @@ static void megasas_free_cmds(struct megasas_instance *instance) * This array is used only to look up the megasas_cmd given the context. The * free commands themselves are maintained in a linked list called cmd_pool. */ -static int megasas_alloc_cmds(struct megasas_instance *instance) +int megasas_alloc_cmds(struct megasas_instance *instance) { int i; int j; u32 max_cmd; struct megasas_cmd *cmd; - max_cmd = instance->max_fw_cmds; + max_cmd = instance->max_mfi_cmds; /* * instance->cmd_list is an array of struct megasas_cmd pointers. @@ -2875,6 +2956,7 @@ static int megasas_alloc_cmds(struct megasas_instance *instance) return -ENOMEM; } + memset(instance->cmd_list, 0, sizeof(struct megasas_cmd *) *max_cmd); for (i = 0; i < max_cmd; i++) { instance->cmd_list[i] = kmalloc(sizeof(struct megasas_cmd), @@ -3288,6 +3370,7 @@ megasas_init_adapter_mfi(struct megasas_instance *instance) * does not exceed max cmds that the FW can support */ instance->max_fw_cmds = instance->max_fw_cmds-1; + instance->max_mfi_cmds = instance->max_fw_cmds; instance->max_num_sge = (instance->instancet->read_fw_status_reg(reg_set) & 0xFF0000) >> 0x10; /* @@ -3381,6 +3464,9 @@ static int megasas_init_fw(struct megasas_instance *instance) reg_set = instance->reg_set; switch (instance->pdev->device) { + case PCI_DEVICE_ID_LSI_FUSION: + instance->instancet = &megasas_instance_template_fusion; + break; case PCI_DEVICE_ID_LSI_SAS1078R: case PCI_DEVICE_ID_LSI_SAS1078DE: instance->instancet = &megasas_instance_template_ppc; @@ -3482,9 +3568,10 @@ fail_ready_state: */ static void megasas_release_mfi(struct megasas_instance *instance) { - u32 reply_q_sz = sizeof(u32) * (instance->max_fw_cmds + 1); + u32 reply_q_sz = sizeof(u32) *(instance->max_mfi_cmds + 1); - pci_free_consistent(instance->pdev, reply_q_sz, + if (instance->reply_queue) + pci_free_consistent(instance->pdev, reply_q_sz, instance->reply_queue, instance->reply_queue_h); megasas_free_cmds(instance); @@ -3678,8 +3765,7 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num, /* * Issue the aen registration frame */ - instance->instancet->fire_cmd(instance, - cmd->frame_phys_addr, 0, instance->reg_set); + instance->instancet->issue_dcmd(instance, cmd); return 0; } @@ -3756,12 +3842,18 @@ static int megasas_io_attach(struct megasas_instance *instance) } host->max_sectors = instance->max_sectors_per_req; - host->cmd_per_lun = 128; + host->cmd_per_lun = MEGASAS_DEFAULT_CMD_PER_LUN; host->max_channel = MEGASAS_MAX_CHANNELS - 1; host->max_id = MEGASAS_MAX_DEV_PER_CHANNEL; host->max_lun = MEGASAS_MAX_LUN; host->max_cmd_len = 16; + /* Fusion only supports host reset */ + if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) { + host->hostt->eh_device_reset_handler = NULL; + host->hostt->eh_bus_reset_handler = NULL; + } + /* * Notify the mid-layer about the new controller */ @@ -3846,20 +3938,45 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) instance = (struct megasas_instance *)host->hostdata; memset(instance, 0, sizeof(*instance)); atomic_set( &instance->fw_reset_no_pci_access, 0 ); + instance->pdev = pdev; - instance->producer = pci_alloc_consistent(pdev, sizeof(u32), - &instance->producer_h); - instance->consumer = pci_alloc_consistent(pdev, sizeof(u32), - &instance->consumer_h); + switch (instance->pdev->device) { + case PCI_DEVICE_ID_LSI_FUSION: + { + struct fusion_context *fusion; + + instance->ctrl_context = + kzalloc(sizeof(struct fusion_context), GFP_KERNEL); + if (!instance->ctrl_context) { + printk(KERN_DEBUG "megasas: Failed to allocate " + "memory for Fusion context info\n"); + goto fail_alloc_dma_buf; + } + fusion = instance->ctrl_context; + INIT_LIST_HEAD(&fusion->cmd_pool); + spin_lock_init(&fusion->cmd_pool_lock); + } + break; + default: /* For all other supported controllers */ + + instance->producer = + pci_alloc_consistent(pdev, sizeof(u32), + &instance->producer_h); + instance->consumer = + pci_alloc_consistent(pdev, sizeof(u32), + &instance->consumer_h); + + if (!instance->producer || !instance->consumer) { + printk(KERN_DEBUG "megasas: Failed to allocate" + "memory for producer, consumer\n"); + goto fail_alloc_dma_buf; + } - if (!instance->producer || !instance->consumer) { - printk(KERN_DEBUG "megasas: Failed to allocate memory for " - "producer, consumer\n"); - goto fail_alloc_dma_buf; + *instance->producer = 0; + *instance->consumer = 0; + break; } - *instance->producer = 0; - *instance->consumer = 0; megasas_poll_wait_aen = 0; instance->flag_ieee = 0; instance->ev = NULL; @@ -3895,11 +4012,11 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) spin_lock_init(&poll_aen_lock); mutex_init(&instance->aen_mutex); + mutex_init(&instance->reset_mutex); /* * Initialize PCI related and misc parameters */ - instance->pdev = pdev; instance->host = host; instance->unique_id = pdev->bus->number << 8 | pdev->devfn; instance->init_id = MEGASAS_DEFAULT_INIT_ID; @@ -3917,7 +4034,10 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) instance->last_time = 0; instance->disableOnlineCtrlReset = 1; - INIT_WORK(&instance->work_init, process_fw_state_change_wq); + if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) + INIT_WORK(&instance->work_init, megasas_fusion_ocr_wq); + else + INIT_WORK(&instance->work_init, process_fw_state_change_wq); /* * Initialize MFI Firmware @@ -4000,6 +4120,8 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) pci_free_consistent(pdev, sizeof(u32), instance->producer, instance->producer_h); megasas_release_mfi(instance); + } else { + megasas_release_fusion(instance); } if (instance->consumer) pci_free_consistent(pdev, sizeof(u32), instance->consumer, @@ -4072,7 +4194,9 @@ static void megasas_shutdown_controller(struct megasas_instance *instance, if (instance->aen_cmd) megasas_issue_blocked_abort_cmd(instance, instance->aen_cmd); - + if (instance->map_update_cmd) + megasas_issue_blocked_abort_cmd(instance, + instance->map_update_cmd); dcmd = &cmd->frame->dcmd; memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); @@ -4177,9 +4301,6 @@ megasas_resume(struct pci_dev *pdev) * Initialize MFI Firmware */ - *instance->producer = 0; - *instance->consumer = 0; - atomic_set(&instance->fw_outstanding, 0); /* @@ -4188,11 +4309,29 @@ megasas_resume(struct pci_dev *pdev) if (megasas_transition_to_ready(instance)) goto fail_ready_state; - if (megasas_issue_init_mfi(instance)) - goto fail_init_mfi; + switch (instance->pdev->device) { + case PCI_DEVICE_ID_LSI_FUSION: + { + megasas_reset_reply_desc(instance); + if (megasas_ioc_init_fusion(instance)) { + megasas_free_cmds(instance); + megasas_free_cmds_fusion(instance); + goto fail_init_mfi; + } + if (!megasas_get_map_info(instance)) + megasas_sync_map_info(instance); + } + break; + default: + *instance->producer = 0; + *instance->consumer = 0; + if (megasas_issue_init_mfi(instance)) + goto fail_init_mfi; + break; + } - tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc, - (unsigned long)instance); + tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet, + (unsigned long)instance); /* Now re-enable MSI-X */ if (instance->msi_flag) @@ -4261,10 +4400,12 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev) int i; struct Scsi_Host *host; struct megasas_instance *instance; + struct fusion_context *fusion; instance = pci_get_drvdata(pdev); instance->unload = 1; host = instance->host; + fusion = instance->ctrl_context; if (poll_mode_io) del_timer_sync(&instance->io_completion_timer); @@ -4306,16 +4447,32 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev) if (instance->msi_flag) pci_disable_msix(instance->pdev); - megasas_release_mfi(instance); - - pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), - instance->evt_detail, instance->evt_detail_h); - - pci_free_consistent(pdev, sizeof(u32), instance->producer, - instance->producer_h); - - pci_free_consistent(pdev, sizeof(u32), instance->consumer, - instance->consumer_h); + switch (instance->pdev->device) { + case PCI_DEVICE_ID_LSI_FUSION: + megasas_release_fusion(instance); + for (i = 0; i < 2 ; i++) + if (fusion->ld_map[i]) + dma_free_coherent(&instance->pdev->dev, + fusion->map_sz, + fusion->ld_map[i], + fusion-> + ld_map_phys[i]); + kfree(instance->ctrl_context); + break; + default: + megasas_release_mfi(instance); + pci_free_consistent(pdev, + sizeof(struct megasas_evt_detail), + instance->evt_detail, + instance->evt_detail_h); + pci_free_consistent(pdev, sizeof(u32), + instance->producer, + instance->producer_h); + pci_free_consistent(pdev, sizeof(u32), + instance->consumer, + instance->consumer_h); + break; + } scsi_host_put(host); @@ -5079,6 +5236,7 @@ megasas_aen_polling(struct work_struct *work) break; case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED: case MR_EVT_FOREIGN_CFG_IMPORTED: + case MR_EVT_LD_STATE_CHANGE: doscan = 1; break; default: diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c new file mode 100644 index 000000000000..53fa96ae2b3e --- /dev/null +++ b/drivers/scsi/megaraid/megaraid_sas_fp.c @@ -0,0 +1,516 @@ +/* + * Linux MegaRAID driver for SAS based RAID controllers + * + * Copyright (c) 2009-2011 LSI Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * FILE: megaraid_sas_fp.c + * + * Authors: LSI Corporation + * Sumant Patro + * Varad Talamacki + * Manoj Jose + * + * Send feedback to: + * + * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035 + * ATTN: Linuxraid + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "megaraid_sas_fusion.h" +#include + +#define ABS_DIFF(a, b) (((a) > (b)) ? ((a) - (b)) : ((b) - (a))) +#define MR_LD_STATE_OPTIMAL 3 +#define FALSE 0 +#define TRUE 1 + +/* Prototypes */ +void +mr_update_load_balance_params(struct MR_FW_RAID_MAP_ALL *map, + struct LD_LOAD_BALANCE_INFO *lbInfo); + +u32 mega_mod64(u64 dividend, u32 divisor) +{ + u64 d; + u32 remainder; + + if (!divisor) + printk(KERN_ERR "megasas : DIVISOR is zero, in div fn\n"); + d = dividend; + remainder = do_div(d, divisor); + return remainder; +} + +/** + * @param dividend : Dividend + * @param divisor : Divisor + * + * @return quotient + **/ +u64 mega_div64_32(uint64_t dividend, uint32_t divisor) +{ + u32 remainder; + u64 d; + + if (!divisor) + printk(KERN_ERR "megasas : DIVISOR is zero in mod fn\n"); + + d = dividend; + remainder = do_div(d, divisor); + + return d; +} + +struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_FW_RAID_MAP_ALL *map) +{ + return &map->raidMap.ldSpanMap[ld].ldRaid; +} + +static struct MR_SPAN_BLOCK_INFO *MR_LdSpanInfoGet(u32 ld, + struct MR_FW_RAID_MAP_ALL + *map) +{ + return &map->raidMap.ldSpanMap[ld].spanBlock[0]; +} + +static u8 MR_LdDataArmGet(u32 ld, u32 armIdx, struct MR_FW_RAID_MAP_ALL *map) +{ + return map->raidMap.ldSpanMap[ld].dataArmMap[armIdx]; +} + +static u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_FW_RAID_MAP_ALL *map) +{ + return map->raidMap.arMapInfo[ar].pd[arm]; +} + +static u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_FW_RAID_MAP_ALL *map) +{ + return map->raidMap.ldSpanMap[ld].spanBlock[span].span.arrayRef; +} + +static u16 MR_PdDevHandleGet(u32 pd, struct MR_FW_RAID_MAP_ALL *map) +{ + return map->raidMap.devHndlInfo[pd].curDevHdl; +} + +u16 MR_GetLDTgtId(u32 ld, struct MR_FW_RAID_MAP_ALL *map) +{ + return map->raidMap.ldSpanMap[ld].ldRaid.targetId; +} + +u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_FW_RAID_MAP_ALL *map) +{ + return map->raidMap.ldTgtIdToLd[ldTgtId]; +} + +static struct MR_LD_SPAN *MR_LdSpanPtrGet(u32 ld, u32 span, + struct MR_FW_RAID_MAP_ALL *map) +{ + return &map->raidMap.ldSpanMap[ld].spanBlock[span].span; +} + +/* + * This function will validate Map info data provided by FW + */ +u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map, + struct LD_LOAD_BALANCE_INFO *lbInfo) +{ + struct MR_FW_RAID_MAP *pFwRaidMap = &map->raidMap; + + if (pFwRaidMap->totalSize != + (sizeof(struct MR_FW_RAID_MAP) -sizeof(struct MR_LD_SPAN_MAP) + + (sizeof(struct MR_LD_SPAN_MAP) *pFwRaidMap->ldCount))) { + printk(KERN_ERR "megasas: map info structure size 0x%x is not matching with ld count\n", + (unsigned int)((sizeof(struct MR_FW_RAID_MAP) - + sizeof(struct MR_LD_SPAN_MAP)) + + (sizeof(struct MR_LD_SPAN_MAP) * + pFwRaidMap->ldCount))); + printk(KERN_ERR "megasas: span map %x, pFwRaidMap->totalSize " + ": %x\n", (unsigned int)sizeof(struct MR_LD_SPAN_MAP), + pFwRaidMap->totalSize); + return 0; + } + + mr_update_load_balance_params(map, lbInfo); + + return 1; +} + +u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk, + struct MR_FW_RAID_MAP_ALL *map, int *div_error) +{ + struct MR_SPAN_BLOCK_INFO *pSpanBlock = MR_LdSpanInfoGet(ld, map); + struct MR_QUAD_ELEMENT *quad; + struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); + u32 span, j; + + for (span = 0; span < raid->spanDepth; span++, pSpanBlock++) { + + for (j = 0; j < pSpanBlock->block_span_info.noElements; j++) { + quad = &pSpanBlock->block_span_info.quad[j]; + + if (quad->diff == 0) { + *div_error = 1; + return span; + } + if (quad->logStart <= row && row <= quad->logEnd && + (mega_mod64(row-quad->logStart, quad->diff)) == 0) { + if (span_blk != NULL) { + u64 blk, debugBlk; + blk = + mega_div64_32( + (row-quad->logStart), + quad->diff); + debugBlk = blk; + + blk = (blk + quad->offsetInSpan) << + raid->stripeShift; + *span_blk = blk; + } + return span; + } + } + } + return span; +} + +/* +****************************************************************************** +* +* This routine calculates the arm, span and block for the specified stripe and +* reference in stripe. +* +* Inputs : +* +* ld - Logical drive number +* stripRow - Stripe number +* stripRef - Reference in stripe +* +* Outputs : +* +* span - Span number +* block - Absolute Block number in the physical disk +*/ +u8 MR_GetPhyParams(u32 ld, u64 stripRow, u16 stripRef, u64 *pdBlock, + u16 *pDevHandle, struct RAID_CONTEXT *pRAID_Context, + struct MR_FW_RAID_MAP_ALL *map) +{ + struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); + u32 pd, arRef; + u8 physArm, span; + u64 row; + u8 retval = TRUE; + int error_code = 0; + + row = mega_div64_32(stripRow, raid->rowDataSize); + + if (raid->level == 6) { + /* logical arm within row */ + u32 logArm = mega_mod64(stripRow, raid->rowDataSize); + u32 rowMod, armQ, arm; + + if (raid->rowSize == 0) + return FALSE; + /* get logical row mod */ + rowMod = mega_mod64(row, raid->rowSize); + armQ = raid->rowSize-1-rowMod; /* index of Q drive */ + arm = armQ+1+logArm; /* data always logically follows Q */ + if (arm >= raid->rowSize) /* handle wrap condition */ + arm -= raid->rowSize; + physArm = (u8)arm; + } else { + if (raid->modFactor == 0) + return FALSE; + physArm = MR_LdDataArmGet(ld, mega_mod64(stripRow, + raid->modFactor), + map); + } + + if (raid->spanDepth == 1) { + span = 0; + *pdBlock = row << raid->stripeShift; + } else { + span = (u8)MR_GetSpanBlock(ld, row, pdBlock, map, &error_code); + if (error_code == 1) + return FALSE; + } + + /* Get the array on which this span is present */ + arRef = MR_LdSpanArrayGet(ld, span, map); + pd = MR_ArPdGet(arRef, physArm, map); /* Get the pd */ + + if (pd != MR_PD_INVALID) + /* Get dev handle from Pd. */ + *pDevHandle = MR_PdDevHandleGet(pd, map); + else { + *pDevHandle = MR_PD_INVALID; /* set dev handle as invalid. */ + if (raid->level >= 5) + pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; + else if (raid->level == 1) { + /* Get alternate Pd. */ + pd = MR_ArPdGet(arRef, physArm + 1, map); + if (pd != MR_PD_INVALID) + /* Get dev handle from Pd */ + *pDevHandle = MR_PdDevHandleGet(pd, map); + } + retval = FALSE; + } + + *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk; + pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | + physArm; + return retval; +} + +/* +****************************************************************************** +* +* MR_BuildRaidContext function +* +* This function will initiate command processing. The start/end row and strip +* information is calculated then the lock is acquired. +* This function will return 0 if region lock was acquired OR return num strips +*/ +u8 +MR_BuildRaidContext(struct IO_REQUEST_INFO *io_info, + struct RAID_CONTEXT *pRAID_Context, + struct MR_FW_RAID_MAP_ALL *map) +{ + struct MR_LD_RAID *raid; + u32 ld, stripSize, stripe_mask; + u64 endLba, endStrip, endRow, start_row, start_strip; + u64 regStart; + u32 regSize; + u8 num_strips, numRows; + u16 ref_in_start_stripe, ref_in_end_stripe; + u64 ldStartBlock; + u32 numBlocks, ldTgtId; + u8 isRead; + u8 retval = 0; + + ldStartBlock = io_info->ldStartBlock; + numBlocks = io_info->numBlocks; + ldTgtId = io_info->ldTgtId; + isRead = io_info->isRead; + + ld = MR_TargetIdToLdGet(ldTgtId, map); + raid = MR_LdRaidGet(ld, map); + + stripSize = 1 << raid->stripeShift; + stripe_mask = stripSize-1; + /* + * calculate starting row and stripe, and number of strips and rows + */ + start_strip = ldStartBlock >> raid->stripeShift; + ref_in_start_stripe = (u16)(ldStartBlock & stripe_mask); + endLba = ldStartBlock + numBlocks - 1; + ref_in_end_stripe = (u16)(endLba & stripe_mask); + endStrip = endLba >> raid->stripeShift; + num_strips = (u8)(endStrip - start_strip + 1); /* End strip */ + if (raid->rowDataSize == 0) + return FALSE; + start_row = mega_div64_32(start_strip, raid->rowDataSize); + endRow = mega_div64_32(endStrip, raid->rowDataSize); + numRows = (u8)(endRow - start_row + 1); + + /* + * calculate region info. + */ + + /* assume region is at the start of the first row */ + regStart = start_row << raid->stripeShift; + /* assume this IO needs the full row - we'll adjust if not true */ + regSize = stripSize; + + /* If IO spans more than 1 strip, fp is not possible + FP is not possible for writes on non-0 raid levels + FP is not possible if LD is not capable */ + if (num_strips > 1 || (!isRead && raid->level != 0) || + !raid->capability.fpCapable) { + io_info->fpOkForIo = FALSE; + } else { + io_info->fpOkForIo = TRUE; + } + + if (numRows == 1) { + /* single-strip IOs can always lock only the data needed */ + if (num_strips == 1) { + regStart += ref_in_start_stripe; + regSize = numBlocks; + } + /* multi-strip IOs always need to full stripe locked */ + } else { + if (start_strip == (start_row + 1) * raid->rowDataSize - 1) { + /* If the start strip is the last in the start row */ + regStart += ref_in_start_stripe; + regSize = stripSize - ref_in_start_stripe; + /* initialize count to sectors from startref to end + of strip */ + } + + if (numRows > 2) + /* Add complete rows in the middle of the transfer */ + regSize += (numRows-2) << raid->stripeShift; + + /* if IO ends within first strip of last row */ + if (endStrip == endRow*raid->rowDataSize) + regSize += ref_in_end_stripe+1; + else + regSize += stripSize; + } + + pRAID_Context->timeoutValue = map->raidMap.fpPdIoTimeoutSec; + pRAID_Context->regLockFlags = (isRead) ? REGION_TYPE_SHARED_READ : + raid->regTypeReqOnWrite; + pRAID_Context->VirtualDiskTgtId = raid->targetId; + pRAID_Context->regLockRowLBA = regStart; + pRAID_Context->regLockLength = regSize; + pRAID_Context->configSeqNum = raid->seqNum; + + /*Get Phy Params only if FP capable, or else leave it to MR firmware + to do the calculation.*/ + if (io_info->fpOkForIo) { + retval = MR_GetPhyParams(ld, start_strip, ref_in_start_stripe, + &io_info->pdBlock, + &io_info->devHandle, pRAID_Context, + map); + /* If IO on an invalid Pd, then FP i snot possible */ + if (io_info->devHandle == MR_PD_INVALID) + io_info->fpOkForIo = FALSE; + return retval; + } else if (isRead) { + uint stripIdx; + for (stripIdx = 0; stripIdx < num_strips; stripIdx++) { + if (!MR_GetPhyParams(ld, start_strip + stripIdx, + ref_in_start_stripe, + &io_info->pdBlock, + &io_info->devHandle, + pRAID_Context, map)) + return TRUE; + } + } + return TRUE; +} + +void +mr_update_load_balance_params(struct MR_FW_RAID_MAP_ALL *map, + struct LD_LOAD_BALANCE_INFO *lbInfo) +{ + int ldCount; + u16 ld; + struct MR_LD_RAID *raid; + + for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) { + ld = MR_TargetIdToLdGet(ldCount, map); + if (ld >= MAX_LOGICAL_DRIVES) { + lbInfo[ldCount].loadBalanceFlag = 0; + continue; + } + + raid = MR_LdRaidGet(ld, map); + + /* Two drive Optimal RAID 1 */ + if ((raid->level == 1) && (raid->rowSize == 2) && + (raid->spanDepth == 1) && raid->ldState == + MR_LD_STATE_OPTIMAL) { + u32 pd, arRef; + + lbInfo[ldCount].loadBalanceFlag = 1; + + /* Get the array on which this span is present */ + arRef = MR_LdSpanArrayGet(ld, 0, map); + + /* Get the Pd */ + pd = MR_ArPdGet(arRef, 0, map); + /* Get dev handle from Pd */ + lbInfo[ldCount].raid1DevHandle[0] = + MR_PdDevHandleGet(pd, map); + /* Get the Pd */ + pd = MR_ArPdGet(arRef, 1, map); + + /* Get the dev handle from Pd */ + lbInfo[ldCount].raid1DevHandle[1] = + MR_PdDevHandleGet(pd, map); + } else + lbInfo[ldCount].loadBalanceFlag = 0; + } +} + +u8 megasas_get_best_arm(struct LD_LOAD_BALANCE_INFO *lbInfo, u8 arm, u64 block, + u32 count) +{ + u16 pend0, pend1; + u64 diff0, diff1; + u8 bestArm; + + /* get the pending cmds for the data and mirror arms */ + pend0 = atomic_read(&lbInfo->scsi_pending_cmds[0]); + pend1 = atomic_read(&lbInfo->scsi_pending_cmds[1]); + + /* Determine the disk whose head is nearer to the req. block */ + diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[0]); + diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[1]); + bestArm = (diff0 <= diff1 ? 0 : 1); + + if ((bestArm == arm && pend0 > pend1 + 16) || + (bestArm != arm && pend1 > pend0 + 16)) + bestArm ^= 1; + + /* Update the last accessed block on the correct pd */ + lbInfo->last_accessed_block[bestArm] = block + count - 1; + + return bestArm; +} + +u16 get_updated_dev_handle(struct LD_LOAD_BALANCE_INFO *lbInfo, + struct IO_REQUEST_INFO *io_info) +{ + u8 arm, old_arm; + u16 devHandle; + + old_arm = lbInfo->raid1DevHandle[0] == io_info->devHandle ? 0 : 1; + + /* get best new arm */ + arm = megasas_get_best_arm(lbInfo, old_arm, io_info->ldStartBlock, + io_info->numBlocks); + devHandle = lbInfo->raid1DevHandle[arm]; + atomic_inc(&lbInfo->scsi_pending_cmds[arm]); + + return devHandle; +} diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c new file mode 100644 index 000000000000..c1e09d5a6196 --- /dev/null +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -0,0 +1,2248 @@ +/* + * Linux MegaRAID driver for SAS based RAID controllers + * + * Copyright (c) 2009-2011 LSI Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * FILE: megaraid_sas_fusion.c + * + * Authors: LSI Corporation + * Sumant Patro + * Adam Radford + * + * Send feedback to: + * + * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035 + * ATTN: Linuxraid + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "megaraid_sas_fusion.h" +#include "megaraid_sas.h" + +extern void megasas_free_cmds(struct megasas_instance *instance); +extern struct megasas_cmd *megasas_get_cmd(struct megasas_instance + *instance); +extern void +megasas_complete_cmd(struct megasas_instance *instance, + struct megasas_cmd *cmd, u8 alt_status); +int megasas_is_ldio(struct scsi_cmnd *cmd); +int +wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd); + +void +megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd); +int megasas_alloc_cmds(struct megasas_instance *instance); +int +megasas_clear_intr_fusion(struct megasas_register_set __iomem *regs); +int +megasas_issue_polled(struct megasas_instance *instance, + struct megasas_cmd *cmd); + +u8 +MR_BuildRaidContext(struct IO_REQUEST_INFO *io_info, + struct RAID_CONTEXT *pRAID_Context, + struct MR_FW_RAID_MAP_ALL *map); +u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_FW_RAID_MAP_ALL *map); +struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_FW_RAID_MAP_ALL *map); + +u16 MR_GetLDTgtId(u32 ld, struct MR_FW_RAID_MAP_ALL *map); +u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map, + struct LD_LOAD_BALANCE_INFO *lbInfo); +u16 get_updated_dev_handle(struct LD_LOAD_BALANCE_INFO *lbInfo, + struct IO_REQUEST_INFO *in_info); +int megasas_transition_to_ready(struct megasas_instance *instance); +void megaraid_sas_kill_hba(struct megasas_instance *instance); + +extern u32 megasas_dbg_lvl; + +/** + * megasas_enable_intr_fusion - Enables interrupts + * @regs: MFI register set + */ +void +megasas_enable_intr_fusion(struct megasas_register_set __iomem *regs) +{ + writel(~MFI_FUSION_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask); + + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_mask); +} + +/** + * megasas_disable_intr_fusion - Disables interrupt + * @regs: MFI register set + */ +void +megasas_disable_intr_fusion(struct megasas_register_set __iomem *regs) +{ + u32 mask = 0xFFFFFFFF; + u32 status; + + writel(mask, ®s->outbound_intr_mask); + /* Dummy readl to force pci flush */ + status = readl(®s->outbound_intr_mask); +} + +int +megasas_clear_intr_fusion(struct megasas_register_set __iomem *regs) +{ + u32 status; + /* + * Check if it is our interrupt + */ + status = readl(®s->outbound_intr_status); + + if (status & 1) { + writel(status, ®s->outbound_intr_status); + readl(®s->outbound_intr_status); + return 1; + } + if (!(status & MFI_FUSION_ENABLE_INTERRUPT_MASK)) + return 0; + + /* + * dummy read to flush PCI + */ + readl(®s->outbound_intr_status); + + return 1; +} + +/** + * megasas_get_cmd_fusion - Get a command from the free pool + * @instance: Adapter soft state + * + * Returns a free command from the pool + */ +struct megasas_cmd_fusion *megasas_get_cmd_fusion(struct megasas_instance + *instance) +{ + unsigned long flags; + struct fusion_context *fusion = + (struct fusion_context *)instance->ctrl_context; + struct megasas_cmd_fusion *cmd = NULL; + + spin_lock_irqsave(&fusion->cmd_pool_lock, flags); + + if (!list_empty(&fusion->cmd_pool)) { + cmd = list_entry((&fusion->cmd_pool)->next, + struct megasas_cmd_fusion, list); + list_del_init(&cmd->list); + } else { + printk(KERN_ERR "megasas: Command pool (fusion) empty!\n"); + } + + spin_unlock_irqrestore(&fusion->cmd_pool_lock, flags); + return cmd; +} + +/** + * megasas_return_cmd_fusion - Return a cmd to free command pool + * @instance: Adapter soft state + * @cmd: Command packet to be returned to free command pool + */ +static inline void +megasas_return_cmd_fusion(struct megasas_instance *instance, + struct megasas_cmd_fusion *cmd) +{ + unsigned long flags; + struct fusion_context *fusion = + (struct fusion_context *)instance->ctrl_context; + + spin_lock_irqsave(&fusion->cmd_pool_lock, flags); + + cmd->scmd = NULL; + cmd->sync_cmd_idx = (u32)ULONG_MAX; + list_add_tail(&cmd->list, &fusion->cmd_pool); + + spin_unlock_irqrestore(&fusion->cmd_pool_lock, flags); +} + +/** + * megasas_teardown_frame_pool_fusion - Destroy the cmd frame DMA pool + * @instance: Adapter soft state + */ +static void megasas_teardown_frame_pool_fusion( + struct megasas_instance *instance) +{ + int i; + struct fusion_context *fusion = instance->ctrl_context; + + u16 max_cmd = instance->max_fw_cmds; + + struct megasas_cmd_fusion *cmd; + + if (!fusion->sg_dma_pool || !fusion->sense_dma_pool) { + printk(KERN_ERR "megasas: dma pool is null. SG Pool %p, " + "sense pool : %p\n", fusion->sg_dma_pool, + fusion->sense_dma_pool); + return; + } + + /* + * Return all frames to pool + */ + for (i = 0; i < max_cmd; i++) { + + cmd = fusion->cmd_list[i]; + + if (cmd->sg_frame) + pci_pool_free(fusion->sg_dma_pool, cmd->sg_frame, + cmd->sg_frame_phys_addr); + + if (cmd->sense) + pci_pool_free(fusion->sense_dma_pool, cmd->sense, + cmd->sense_phys_addr); + } + + /* + * Now destroy the pool itself + */ + pci_pool_destroy(fusion->sg_dma_pool); + pci_pool_destroy(fusion->sense_dma_pool); + + fusion->sg_dma_pool = NULL; + fusion->sense_dma_pool = NULL; +} + +/** + * megasas_free_cmds_fusion - Free all the cmds in the free cmd pool + * @instance: Adapter soft state + */ +void +megasas_free_cmds_fusion(struct megasas_instance *instance) +{ + int i; + struct fusion_context *fusion = instance->ctrl_context; + + u32 max_cmds, req_sz, reply_sz, io_frames_sz; + + + req_sz = fusion->request_alloc_sz; + reply_sz = fusion->reply_alloc_sz; + io_frames_sz = fusion->io_frames_alloc_sz; + + max_cmds = instance->max_fw_cmds; + + /* Free descriptors and request Frames memory */ + if (fusion->req_frames_desc) + dma_free_coherent(&instance->pdev->dev, req_sz, + fusion->req_frames_desc, + fusion->req_frames_desc_phys); + + if (fusion->reply_frames_desc) { + pci_pool_free(fusion->reply_frames_desc_pool, + fusion->reply_frames_desc, + fusion->reply_frames_desc_phys); + pci_pool_destroy(fusion->reply_frames_desc_pool); + } + + if (fusion->io_request_frames) { + pci_pool_free(fusion->io_request_frames_pool, + fusion->io_request_frames, + fusion->io_request_frames_phys); + pci_pool_destroy(fusion->io_request_frames_pool); + } + + /* Free the Fusion frame pool */ + megasas_teardown_frame_pool_fusion(instance); + + /* Free all the commands in the cmd_list */ + for (i = 0; i < max_cmds; i++) + kfree(fusion->cmd_list[i]); + + /* Free the cmd_list buffer itself */ + kfree(fusion->cmd_list); + fusion->cmd_list = NULL; + + INIT_LIST_HEAD(&fusion->cmd_pool); +} + +/** + * megasas_create_frame_pool_fusion - Creates DMA pool for cmd frames + * @instance: Adapter soft state + * + */ +static int megasas_create_frame_pool_fusion(struct megasas_instance *instance) +{ + int i; + u32 max_cmd; + struct fusion_context *fusion; + struct megasas_cmd_fusion *cmd; + u32 total_sz_chain_frame; + + fusion = instance->ctrl_context; + max_cmd = instance->max_fw_cmds; + + total_sz_chain_frame = MEGASAS_MAX_SZ_CHAIN_FRAME; + + /* + * Use DMA pool facility provided by PCI layer + */ + + fusion->sg_dma_pool = pci_pool_create("megasas sg pool fusion", + instance->pdev, + total_sz_chain_frame, 4, + 0); + if (!fusion->sg_dma_pool) { + printk(KERN_DEBUG "megasas: failed to setup request pool " + "fusion\n"); + return -ENOMEM; + } + fusion->sense_dma_pool = pci_pool_create("megasas sense pool fusion", + instance->pdev, + SCSI_SENSE_BUFFERSIZE, 64, 0); + + if (!fusion->sense_dma_pool) { + printk(KERN_DEBUG "megasas: failed to setup sense pool " + "fusion\n"); + pci_pool_destroy(fusion->sg_dma_pool); + fusion->sg_dma_pool = NULL; + return -ENOMEM; + } + + /* + * Allocate and attach a frame to each of the commands in cmd_list + */ + for (i = 0; i < max_cmd; i++) { + + cmd = fusion->cmd_list[i]; + + cmd->sg_frame = pci_pool_alloc(fusion->sg_dma_pool, + GFP_KERNEL, + &cmd->sg_frame_phys_addr); + + cmd->sense = pci_pool_alloc(fusion->sense_dma_pool, + GFP_KERNEL, &cmd->sense_phys_addr); + /* + * megasas_teardown_frame_pool_fusion() takes care of freeing + * whatever has been allocated + */ + if (!cmd->sg_frame || !cmd->sense) { + printk(KERN_DEBUG "megasas: pci_pool_alloc failed\n"); + megasas_teardown_frame_pool_fusion(instance); + return -ENOMEM; + } + } + return 0; +} + +/** + * megasas_alloc_cmds_fusion - Allocates the command packets + * @instance: Adapter soft state + * + * + * Each frame has a 32-bit field called context. This context is used to get + * back the megasas_cmd_fusion from the frame when a frame gets completed + * In this driver, the 32 bit values are the indices into an array cmd_list. + * This array is used only to look up the megasas_cmd_fusion given the context. + * The free commands themselves are maintained in a linked list called cmd_pool. + * + * cmds are formed in the io_request and sg_frame members of the + * megasas_cmd_fusion. The context field is used to get a request descriptor + * and is used as SMID of the cmd. + * SMID value range is from 1 to max_fw_cmds. + */ +int +megasas_alloc_cmds_fusion(struct megasas_instance *instance) +{ + int i, j; + u32 max_cmd, io_frames_sz; + struct fusion_context *fusion; + struct megasas_cmd_fusion *cmd; + union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc; + u32 offset; + dma_addr_t io_req_base_phys; + u8 *io_req_base; + + fusion = instance->ctrl_context; + + max_cmd = instance->max_fw_cmds; + + fusion->req_frames_desc = + dma_alloc_coherent(&instance->pdev->dev, + fusion->request_alloc_sz, + &fusion->req_frames_desc_phys, GFP_KERNEL); + + if (!fusion->req_frames_desc) { + printk(KERN_ERR "megasas; Could not allocate memory for " + "request_frames\n"); + goto fail_req_desc; + } + + fusion->reply_frames_desc_pool = + pci_pool_create("reply_frames pool", instance->pdev, + fusion->reply_alloc_sz, 16, 0); + + if (!fusion->reply_frames_desc_pool) { + printk(KERN_ERR "megasas; Could not allocate memory for " + "reply_frame pool\n"); + goto fail_reply_desc; + } + + fusion->reply_frames_desc = + pci_pool_alloc(fusion->reply_frames_desc_pool, GFP_KERNEL, + &fusion->reply_frames_desc_phys); + if (!fusion->reply_frames_desc) { + printk(KERN_ERR "megasas; Could not allocate memory for " + "reply_frame pool\n"); + pci_pool_destroy(fusion->reply_frames_desc_pool); + goto fail_reply_desc; + } + + reply_desc = fusion->reply_frames_desc; + for (i = 0; i < fusion->reply_q_depth; i++, reply_desc++) + reply_desc->Words = ULLONG_MAX; + + io_frames_sz = fusion->io_frames_alloc_sz; + + fusion->io_request_frames_pool = + pci_pool_create("io_request_frames pool", instance->pdev, + fusion->io_frames_alloc_sz, 16, 0); + + if (!fusion->io_request_frames_pool) { + printk(KERN_ERR "megasas: Could not allocate memory for " + "io_request_frame pool\n"); + goto fail_io_frames; + } + + fusion->io_request_frames = + pci_pool_alloc(fusion->io_request_frames_pool, GFP_KERNEL, + &fusion->io_request_frames_phys); + if (!fusion->io_request_frames) { + printk(KERN_ERR "megasas: Could not allocate memory for " + "io_request_frames frames\n"); + pci_pool_destroy(fusion->io_request_frames_pool); + goto fail_io_frames; + } + + /* + * fusion->cmd_list is an array of struct megasas_cmd_fusion pointers. + * Allocate the dynamic array first and then allocate individual + * commands. + */ + fusion->cmd_list = kmalloc(sizeof(struct megasas_cmd_fusion *) + *max_cmd, GFP_KERNEL); + + if (!fusion->cmd_list) { + printk(KERN_DEBUG "megasas: out of memory. Could not alloc " + "memory for cmd_list_fusion\n"); + goto fail_cmd_list; + } + + memset(fusion->cmd_list, 0, sizeof(struct megasas_cmd_fusion *) + *max_cmd); + + max_cmd = instance->max_fw_cmds; + for (i = 0; i < max_cmd; i++) { + fusion->cmd_list[i] = kmalloc(sizeof(struct megasas_cmd_fusion), + GFP_KERNEL); + if (!fusion->cmd_list[i]) { + printk(KERN_ERR "Could not alloc cmd list fusion\n"); + + for (j = 0; j < i; j++) + kfree(fusion->cmd_list[j]); + + kfree(fusion->cmd_list); + fusion->cmd_list = NULL; + goto fail_cmd_list; + } + } + + /* The first 256 bytes (SMID 0) is not used. Don't add to cmd list */ + io_req_base = fusion->io_request_frames + + MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE; + io_req_base_phys = fusion->io_request_frames_phys + + MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE; + + /* + * Add all the commands to command pool (fusion->cmd_pool) + */ + + /* SMID 0 is reserved. Set SMID/index from 1 */ + for (i = 0; i < max_cmd; i++) { + cmd = fusion->cmd_list[i]; + offset = MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * i; + memset(cmd, 0, sizeof(struct megasas_cmd_fusion)); + cmd->index = i + 1; + cmd->scmd = NULL; + cmd->sync_cmd_idx = (u32)ULONG_MAX; /* Set to Invalid */ + cmd->instance = instance; + cmd->io_request = + (struct MPI2_RAID_SCSI_IO_REQUEST *) + (io_req_base + offset); + memset(cmd->io_request, 0, + sizeof(struct MPI2_RAID_SCSI_IO_REQUEST)); + cmd->io_request_phys_addr = io_req_base_phys + offset; + + list_add_tail(&cmd->list, &fusion->cmd_pool); + } + + /* + * Create a frame pool and assign one frame to each cmd + */ + if (megasas_create_frame_pool_fusion(instance)) { + printk(KERN_DEBUG "megasas: Error creating frame DMA pool\n"); + megasas_free_cmds_fusion(instance); + goto fail_req_desc; + } + + return 0; + +fail_cmd_list: + pci_pool_free(fusion->io_request_frames_pool, fusion->io_request_frames, + fusion->io_request_frames_phys); + pci_pool_destroy(fusion->io_request_frames_pool); +fail_io_frames: + dma_free_coherent(&instance->pdev->dev, fusion->request_alloc_sz, + fusion->reply_frames_desc, + fusion->reply_frames_desc_phys); + pci_pool_free(fusion->reply_frames_desc_pool, + fusion->reply_frames_desc, + fusion->reply_frames_desc_phys); + pci_pool_destroy(fusion->reply_frames_desc_pool); + +fail_reply_desc: + dma_free_coherent(&instance->pdev->dev, fusion->request_alloc_sz, + fusion->req_frames_desc, + fusion->req_frames_desc_phys); +fail_req_desc: + return -ENOMEM; +} + +/** + * wait_and_poll - Issues a polling command + * @instance: Adapter soft state + * @cmd: Command packet to be issued + * + * For polling, MFI requires the cmd_status to be set to 0xFF before posting. + */ +int +wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd) +{ + int i; + struct megasas_header *frame_hdr = &cmd->frame->hdr; + + u32 msecs = MFI_POLL_TIMEOUT_SECS * 1000; + + /* + * Wait for cmd_status to change + */ + for (i = 0; (i < msecs) && (frame_hdr->cmd_status == 0xff); i += 20) { + rmb(); + msleep(20); + } + + if (frame_hdr->cmd_status == 0xff) + return -ETIME; + + return 0; +} + +/** + * megasas_ioc_init_fusion - Initializes the FW + * @instance: Adapter soft state + * + * Issues the IOC Init cmd + */ +int +megasas_ioc_init_fusion(struct megasas_instance *instance) +{ + struct megasas_init_frame *init_frame; + struct MPI2_IOC_INIT_REQUEST *IOCInitMessage; + dma_addr_t ioc_init_handle; + u32 context; + struct megasas_cmd *cmd; + u8 ret; + struct fusion_context *fusion; + union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc; + int i; + struct megasas_header *frame_hdr; + + fusion = instance->ctrl_context; + + cmd = megasas_get_cmd(instance); + + if (!cmd) { + printk(KERN_ERR "Could not allocate cmd for INIT Frame\n"); + ret = 1; + goto fail_get_cmd; + } + + IOCInitMessage = + dma_alloc_coherent(&instance->pdev->dev, + sizeof(struct MPI2_IOC_INIT_REQUEST), + &ioc_init_handle, GFP_KERNEL); + + if (!IOCInitMessage) { + printk(KERN_ERR "Could not allocate memory for " + "IOCInitMessage\n"); + ret = 1; + goto fail_fw_init; + } + + memset(IOCInitMessage, 0, sizeof(struct MPI2_IOC_INIT_REQUEST)); + + IOCInitMessage->Function = MPI2_FUNCTION_IOC_INIT; + IOCInitMessage->WhoInit = MPI2_WHOINIT_HOST_DRIVER; + IOCInitMessage->MsgVersion = MPI2_VERSION; + IOCInitMessage->HeaderVersion = MPI2_HEADER_VERSION; + IOCInitMessage->SystemRequestFrameSize = + MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE / 4; + + IOCInitMessage->ReplyDescriptorPostQueueDepth = fusion->reply_q_depth; + IOCInitMessage->ReplyDescriptorPostQueueAddress = + fusion->reply_frames_desc_phys; + IOCInitMessage->SystemRequestFrameBaseAddress = + fusion->io_request_frames_phys; + + init_frame = (struct megasas_init_frame *)cmd->frame; + memset(init_frame, 0, MEGAMFI_FRAME_SIZE); + + frame_hdr = &cmd->frame->hdr; + context = init_frame->context; + init_frame->context = context; + + frame_hdr->cmd_status = 0xFF; + frame_hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE; + + init_frame->cmd = MFI_CMD_INIT; + init_frame->cmd_status = 0xFF; + + init_frame->queue_info_new_phys_addr_lo = ioc_init_handle; + init_frame->data_xfer_len = sizeof(struct MPI2_IOC_INIT_REQUEST); + + req_desc = + (union MEGASAS_REQUEST_DESCRIPTOR_UNION *)fusion->req_frames_desc; + + req_desc->Words = cmd->frame_phys_addr; + req_desc->MFAIo.RequestFlags = + (MEGASAS_REQ_DESCRIPT_FLAGS_MFA << + MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); + + /* + * disable the intr before firing the init frame + */ + instance->instancet->disable_intr(instance->reg_set); + + for (i = 0; i < (10 * 1000); i += 20) { + if (readl(&instance->reg_set->doorbell) & 1) + msleep(20); + else + break; + } + + instance->instancet->fire_cmd(instance, req_desc->u.low, + req_desc->u.high, instance->reg_set); + + wait_and_poll(instance, cmd); + + frame_hdr = &cmd->frame->hdr; + if (frame_hdr->cmd_status != 0) { + ret = 1; + goto fail_fw_init; + } + printk(KERN_ERR "megasas:IOC Init cmd success\n"); + + ret = 0; + +fail_fw_init: + megasas_return_cmd(instance, cmd); + if (IOCInitMessage) + dma_free_coherent(&instance->pdev->dev, + sizeof(struct MPI2_IOC_INIT_REQUEST), + IOCInitMessage, ioc_init_handle); +fail_get_cmd: + return ret; +} + +/* + * megasas_return_cmd_for_smid - Returns a cmd_fusion for a SMID + * @instance: Adapter soft state + * + */ +void +megasas_return_cmd_for_smid(struct megasas_instance *instance, u16 smid) +{ + struct fusion_context *fusion; + struct megasas_cmd_fusion *cmd; + + fusion = instance->ctrl_context; + cmd = fusion->cmd_list[smid - 1]; + megasas_return_cmd_fusion(instance, cmd); +} + +/* + * megasas_get_ld_map_info - Returns FW's ld_map structure + * @instance: Adapter soft state + * @pend: Pend the command or not + * Issues an internal command (DCMD) to get the FW's controller PD + * list structure. This information is mainly used to find out SYSTEM + * supported by the FW. + */ +static int +megasas_get_ld_map_info(struct megasas_instance *instance) +{ + int ret = 0; + struct megasas_cmd *cmd; + struct megasas_dcmd_frame *dcmd; + struct MR_FW_RAID_MAP_ALL *ci; + dma_addr_t ci_h = 0; + u32 size_map_info; + struct fusion_context *fusion; + + cmd = megasas_get_cmd(instance); + + if (!cmd) { + printk(KERN_DEBUG "megasas: Failed to get cmd for map info.\n"); + return -ENOMEM; + } + + fusion = instance->ctrl_context; + + if (!fusion) { + megasas_return_cmd(instance, cmd); + return 1; + } + + dcmd = &cmd->frame->dcmd; + + size_map_info = sizeof(struct MR_FW_RAID_MAP) + + (sizeof(struct MR_LD_SPAN_MAP) *(MAX_LOGICAL_DRIVES - 1)); + + ci = fusion->ld_map[(instance->map_id & 1)]; + ci_h = fusion->ld_map_phys[(instance->map_id & 1)]; + + if (!ci) { + printk(KERN_DEBUG "Failed to alloc mem for ld_map_info\n"); + megasas_return_cmd(instance, cmd); + return -ENOMEM; + } + + memset(ci, 0, sizeof(*ci)); + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); + + dcmd->cmd = MFI_CMD_DCMD; + dcmd->cmd_status = 0xFF; + dcmd->sge_count = 1; + dcmd->flags = MFI_FRAME_DIR_READ; + dcmd->timeout = 0; + dcmd->pad_0 = 0; + dcmd->data_xfer_len = size_map_info; + dcmd->opcode = MR_DCMD_LD_MAP_GET_INFO; + dcmd->sgl.sge32[0].phys_addr = ci_h; + dcmd->sgl.sge32[0].length = size_map_info; + + if (!megasas_issue_polled(instance, cmd)) + ret = 0; + else { + printk(KERN_ERR "megasas: Get LD Map Info Failed\n"); + ret = -1; + } + + megasas_return_cmd(instance, cmd); + + return ret; +} + +u8 +megasas_get_map_info(struct megasas_instance *instance) +{ + struct fusion_context *fusion = instance->ctrl_context; + + fusion->fast_path_io = 0; + if (!megasas_get_ld_map_info(instance)) { + if (MR_ValidateMapInfo(fusion->ld_map[(instance->map_id & 1)], + fusion->load_balance_info)) { + fusion->fast_path_io = 1; + return 0; + } + } + return 1; +} + +/* + * megasas_sync_map_info - Returns FW's ld_map structure + * @instance: Adapter soft state + * + * Issues an internal command (DCMD) to get the FW's controller PD + * list structure. This information is mainly used to find out SYSTEM + * supported by the FW. + */ +int +megasas_sync_map_info(struct megasas_instance *instance) +{ + int ret = 0, i; + struct megasas_cmd *cmd; + struct megasas_dcmd_frame *dcmd; + u32 size_sync_info, num_lds; + struct fusion_context *fusion; + struct MR_LD_TARGET_SYNC *ci = NULL; + struct MR_FW_RAID_MAP_ALL *map; + struct MR_LD_RAID *raid; + struct MR_LD_TARGET_SYNC *ld_sync; + dma_addr_t ci_h = 0; + u32 size_map_info; + + cmd = megasas_get_cmd(instance); + + if (!cmd) { + printk(KERN_DEBUG "megasas: Failed to get cmd for sync" + "info.\n"); + return -ENOMEM; + } + + fusion = instance->ctrl_context; + + if (!fusion) { + megasas_return_cmd(instance, cmd); + return 1; + } + + map = fusion->ld_map[instance->map_id & 1]; + + num_lds = map->raidMap.ldCount; + + dcmd = &cmd->frame->dcmd; + + size_sync_info = sizeof(struct MR_LD_TARGET_SYNC) *num_lds; + + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); + + ci = (struct MR_LD_TARGET_SYNC *) + fusion->ld_map[(instance->map_id - 1) & 1]; + memset(ci, 0, sizeof(struct MR_FW_RAID_MAP_ALL)); + + ci_h = fusion->ld_map_phys[(instance->map_id - 1) & 1]; + + ld_sync = (struct MR_LD_TARGET_SYNC *)ci; + + for (i = 0; i < num_lds; i++, ld_sync++) { + raid = MR_LdRaidGet(i, map); + ld_sync->targetId = MR_GetLDTgtId(i, map); + ld_sync->seqNum = raid->seqNum; + } + + size_map_info = sizeof(struct MR_FW_RAID_MAP) + + (sizeof(struct MR_LD_SPAN_MAP) *(MAX_LOGICAL_DRIVES - 1)); + + dcmd->cmd = MFI_CMD_DCMD; + dcmd->cmd_status = 0xFF; + dcmd->sge_count = 1; + dcmd->flags = MFI_FRAME_DIR_WRITE; + dcmd->timeout = 0; + dcmd->pad_0 = 0; + dcmd->data_xfer_len = size_map_info; + dcmd->mbox.b[0] = num_lds; + dcmd->mbox.b[1] = MEGASAS_DCMD_MBOX_PEND_FLAG; + dcmd->opcode = MR_DCMD_LD_MAP_GET_INFO; + dcmd->sgl.sge32[0].phys_addr = ci_h; + dcmd->sgl.sge32[0].length = size_map_info; + + instance->map_update_cmd = cmd; + + instance->instancet->issue_dcmd(instance, cmd); + + return ret; +} + +/** + * megasas_init_adapter_fusion - Initializes the FW + * @instance: Adapter soft state + * + * This is the main function for initializing firmware. + */ +u32 +megasas_init_adapter_fusion(struct megasas_instance *instance) +{ + struct megasas_register_set __iomem *reg_set; + struct fusion_context *fusion; + u32 max_cmd; + int i = 0; + + fusion = instance->ctrl_context; + + reg_set = instance->reg_set; + + /* + * Get various operational parameters from status register + */ + instance->max_fw_cmds = + instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF; + instance->max_fw_cmds = min(instance->max_fw_cmds, (u16)1008); + + /* + * Reduce the max supported cmds by 1. This is to ensure that the + * reply_q_sz (1 more than the max cmd that driver may send) + * does not exceed max cmds that the FW can support + */ + instance->max_fw_cmds = instance->max_fw_cmds-1; + /* Only internal cmds (DCMD) need to have MFI frames */ + instance->max_mfi_cmds = MEGASAS_INT_CMDS; + + max_cmd = instance->max_fw_cmds; + + fusion->reply_q_depth = ((max_cmd + 1 + 15)/16)*16; + + fusion->request_alloc_sz = + sizeof(union MEGASAS_REQUEST_DESCRIPTOR_UNION) *max_cmd; + fusion->reply_alloc_sz = sizeof(union MPI2_REPLY_DESCRIPTORS_UNION) + *(fusion->reply_q_depth); + fusion->io_frames_alloc_sz = MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE + + (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * + (max_cmd + 1)); /* Extra 1 for SMID 0 */ + + fusion->max_sge_in_main_msg = + (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE - + offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL))/16; + + fusion->max_sge_in_chain = + MEGASAS_MAX_SZ_CHAIN_FRAME / sizeof(union MPI2_SGE_IO_UNION); + + instance->max_num_sge = fusion->max_sge_in_main_msg + + fusion->max_sge_in_chain - 2; + + /* Used for pass thru MFI frame (DCMD) */ + fusion->chain_offset_mfi_pthru = + offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL)/16; + + fusion->chain_offset_io_request = + (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE - + sizeof(union MPI2_SGE_IO_UNION))/16; + + fusion->last_reply_idx = 0; + + /* + * Allocate memory for descriptors + * Create a pool of commands + */ + if (megasas_alloc_cmds(instance)) + goto fail_alloc_mfi_cmds; + if (megasas_alloc_cmds_fusion(instance)) + goto fail_alloc_cmds; + + if (megasas_ioc_init_fusion(instance)) + goto fail_ioc_init; + + instance->flag_ieee = 1; + + fusion->map_sz = sizeof(struct MR_FW_RAID_MAP) + + (sizeof(struct MR_LD_SPAN_MAP) *(MAX_LOGICAL_DRIVES - 1)); + + fusion->fast_path_io = 0; + + for (i = 0; i < 2; i++) { + fusion->ld_map[i] = dma_alloc_coherent(&instance->pdev->dev, + fusion->map_sz, + &fusion->ld_map_phys[i], + GFP_KERNEL); + if (!fusion->ld_map[i]) { + printk(KERN_ERR "megasas: Could not allocate memory " + "for map info\n"); + goto fail_map_info; + } + } + + if (!megasas_get_map_info(instance)) + megasas_sync_map_info(instance); + + return 0; + +fail_alloc_cmds: +fail_alloc_mfi_cmds: +fail_map_info: + if (i == 1) + dma_free_coherent(&instance->pdev->dev, fusion->map_sz, + fusion->ld_map[0], fusion->ld_map_phys[0]); +fail_ioc_init: + return 1; +} + +/** + * megasas_fire_cmd_fusion - Sends command to the FW + * @frame_phys_addr : Physical address of cmd + * @frame_count : Number of frames for the command + * @regs : MFI register set + */ +void +megasas_fire_cmd_fusion(struct megasas_instance *instance, + dma_addr_t req_desc_lo, + u32 req_desc_hi, + struct megasas_register_set __iomem *regs) +{ + unsigned long flags; + + spin_lock_irqsave(&instance->hba_lock, flags); + + writel(req_desc_lo, + &(regs)->inbound_low_queue_port); + writel(req_desc_hi, &(regs)->inbound_high_queue_port); + spin_unlock_irqrestore(&instance->hba_lock, flags); +} + +/** + * map_cmd_status - Maps FW cmd status to OS cmd status + * @cmd : Pointer to cmd + * @status : status of cmd returned by FW + * @ext_status : ext status of cmd returned by FW + */ + +void +map_cmd_status(struct megasas_cmd_fusion *cmd, u8 status, u8 ext_status) +{ + + switch (status) { + + case MFI_STAT_OK: + cmd->scmd->result = DID_OK << 16; + break; + + case MFI_STAT_SCSI_IO_FAILED: + case MFI_STAT_LD_INIT_IN_PROGRESS: + cmd->scmd->result = (DID_ERROR << 16) | ext_status; + break; + + case MFI_STAT_SCSI_DONE_WITH_ERROR: + + cmd->scmd->result = (DID_OK << 16) | ext_status; + if (ext_status == SAM_STAT_CHECK_CONDITION) { + memset(cmd->scmd->sense_buffer, 0, + SCSI_SENSE_BUFFERSIZE); + memcpy(cmd->scmd->sense_buffer, cmd->sense, + SCSI_SENSE_BUFFERSIZE); + cmd->scmd->result |= DRIVER_SENSE << 24; + } + break; + + case MFI_STAT_LD_OFFLINE: + case MFI_STAT_DEVICE_NOT_FOUND: + cmd->scmd->result = DID_BAD_TARGET << 16; + break; + + default: + printk(KERN_DEBUG "megasas: FW status %#x\n", status); + cmd->scmd->result = DID_ERROR << 16; + break; + } +} + +/** + * megasas_make_sgl_fusion - Prepares 32-bit SGL + * @instance: Adapter soft state + * @scp: SCSI command from the mid-layer + * @sgl_ptr: SGL to be filled in + * @cmd: cmd we are working on + * + * If successful, this function returns the number of SG elements. + */ +static int +megasas_make_sgl_fusion(struct megasas_instance *instance, + struct scsi_cmnd *scp, + struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr, + struct megasas_cmd_fusion *cmd) +{ + int i, sg_processed; + int sge_count, sge_idx; + struct scatterlist *os_sgl; + struct fusion_context *fusion; + + fusion = instance->ctrl_context; + + cmd->io_request->ChainOffset = 0; + + sge_count = scsi_dma_map(scp); + + BUG_ON(sge_count < 0); + + if (sge_count > instance->max_num_sge || !sge_count) + return sge_count; + + if (sge_count > fusion->max_sge_in_main_msg) { + /* One element to store the chain info */ + sge_idx = fusion->max_sge_in_main_msg - 1; + } else + sge_idx = sge_count; + + scsi_for_each_sg(scp, os_sgl, sge_count, i) { + sgl_ptr->Length = sg_dma_len(os_sgl); + sgl_ptr->Address = sg_dma_address(os_sgl); + sgl_ptr->Flags = 0; + sgl_ptr++; + + sg_processed = i + 1; + + if ((sg_processed == (fusion->max_sge_in_main_msg - 1)) && + (sge_count > fusion->max_sge_in_main_msg)) { + + struct MPI25_IEEE_SGE_CHAIN64 *sg_chain; + cmd->io_request->ChainOffset = + fusion->chain_offset_io_request; + sg_chain = sgl_ptr; + /* Prepare chain element */ + sg_chain->NextChainOffset = 0; + sg_chain->Flags = (IEEE_SGE_FLAGS_CHAIN_ELEMENT | + MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR); + sg_chain->Length = (sizeof(union MPI2_SGE_IO_UNION) + *(sge_count - sg_processed)); + sg_chain->Address = cmd->sg_frame_phys_addr; + + sgl_ptr = + (struct MPI25_IEEE_SGE_CHAIN64 *)cmd->sg_frame; + } + } + + return sge_count; +} + +/** + * megasas_set_pd_lba - Sets PD LBA + * @cdb: CDB + * @cdb_len: cdb length + * @start_blk: Start block of IO + * + * Used to set the PD LBA in CDB for FP IOs + */ +void +megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len, + struct IO_REQUEST_INFO *io_info, struct scsi_cmnd *scp, + struct MR_FW_RAID_MAP_ALL *local_map_ptr, u32 ref_tag) +{ + struct MR_LD_RAID *raid; + u32 ld; + u64 start_blk = io_info->pdBlock; + u8 *cdb = io_request->CDB.CDB32; + u32 num_blocks = io_info->numBlocks; + u8 opcode, flagvals, groupnum, control; + + /* Check if T10 PI (DIF) is enabled for this LD */ + ld = MR_TargetIdToLdGet(io_info->ldTgtId, local_map_ptr); + raid = MR_LdRaidGet(ld, local_map_ptr); + if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER) { + memset(cdb, 0, sizeof(io_request->CDB.CDB32)); + cdb[0] = MEGASAS_SCSI_VARIABLE_LENGTH_CMD; + cdb[7] = MEGASAS_SCSI_ADDL_CDB_LEN; + + if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) + cdb[9] = MEGASAS_SCSI_SERVICE_ACTION_READ32; + else + cdb[9] = MEGASAS_SCSI_SERVICE_ACTION_WRITE32; + cdb[10] = MEGASAS_RD_WR_PROTECT_CHECK_ALL; + + /* LBA */ + cdb[12] = (u8)((start_blk >> 56) & 0xff); + cdb[13] = (u8)((start_blk >> 48) & 0xff); + cdb[14] = (u8)((start_blk >> 40) & 0xff); + cdb[15] = (u8)((start_blk >> 32) & 0xff); + cdb[16] = (u8)((start_blk >> 24) & 0xff); + cdb[17] = (u8)((start_blk >> 16) & 0xff); + cdb[18] = (u8)((start_blk >> 8) & 0xff); + cdb[19] = (u8)(start_blk & 0xff); + + /* Logical block reference tag */ + io_request->CDB.EEDP32.PrimaryReferenceTag = + cpu_to_be32(ref_tag); + io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0xffff; + + io_request->DataLength = num_blocks * 512; + io_request->IoFlags = 32; /* Specify 32-byte cdb */ + + /* Transfer length */ + cdb[28] = (u8)((num_blocks >> 24) & 0xff); + cdb[29] = (u8)((num_blocks >> 16) & 0xff); + cdb[30] = (u8)((num_blocks >> 8) & 0xff); + cdb[31] = (u8)(num_blocks & 0xff); + + /* set SCSI IO EEDPFlags */ + if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) { + io_request->EEDPFlags = + MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | + MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | + MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP | + MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG | + MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; + } else { + io_request->EEDPFlags = + MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | + MPI2_SCSIIO_EEDPFLAGS_INSERT_OP; + } + io_request->Control |= (0x4 << 26); + io_request->EEDPBlockSize = MEGASAS_EEDPBLOCKSIZE; + } else { + /* Some drives don't support 16/12 byte CDB's, convert to 10 */ + if (((cdb_len == 12) || (cdb_len == 16)) && + (start_blk <= 0xffffffff)) { + if (cdb_len == 16) { + opcode = cdb[0] == READ_16 ? READ_10 : WRITE_10; + flagvals = cdb[1]; + groupnum = cdb[14]; + control = cdb[15]; + } else { + opcode = cdb[0] == READ_12 ? READ_10 : WRITE_10; + flagvals = cdb[1]; + groupnum = cdb[10]; + control = cdb[11]; + } + + memset(cdb, 0, sizeof(io_request->CDB.CDB32)); + + cdb[0] = opcode; + cdb[1] = flagvals; + cdb[6] = groupnum; + cdb[9] = control; + + /* Transfer length */ + cdb[8] = (u8)(num_blocks & 0xff); + cdb[7] = (u8)((num_blocks >> 8) & 0xff); + + cdb_len = 10; + } + + /* Normal case, just load LBA here */ + switch (cdb_len) { + case 6: + { + u8 val = cdb[1] & 0xE0; + cdb[3] = (u8)(start_blk & 0xff); + cdb[2] = (u8)((start_blk >> 8) & 0xff); + cdb[1] = val | ((u8)(start_blk >> 16) & 0x1f); + break; + } + case 10: + cdb[5] = (u8)(start_blk & 0xff); + cdb[4] = (u8)((start_blk >> 8) & 0xff); + cdb[3] = (u8)((start_blk >> 16) & 0xff); + cdb[2] = (u8)((start_blk >> 24) & 0xff); + break; + case 12: + cdb[5] = (u8)(start_blk & 0xff); + cdb[4] = (u8)((start_blk >> 8) & 0xff); + cdb[3] = (u8)((start_blk >> 16) & 0xff); + cdb[2] = (u8)((start_blk >> 24) & 0xff); + break; + case 16: + cdb[9] = (u8)(start_blk & 0xff); + cdb[8] = (u8)((start_blk >> 8) & 0xff); + cdb[7] = (u8)((start_blk >> 16) & 0xff); + cdb[6] = (u8)((start_blk >> 24) & 0xff); + cdb[5] = (u8)((start_blk >> 32) & 0xff); + cdb[4] = (u8)((start_blk >> 40) & 0xff); + cdb[3] = (u8)((start_blk >> 48) & 0xff); + cdb[2] = (u8)((start_blk >> 56) & 0xff); + break; + } + } +} + +/** + * megasas_build_ldio_fusion - Prepares IOs to devices + * @instance: Adapter soft state + * @scp: SCSI command + * @cmd: Command to be prepared + * + * Prepares the io_request and chain elements (sg_frame) for IO + * The IO can be for PD (Fast Path) or LD + */ +void +megasas_build_ldio_fusion(struct megasas_instance *instance, + struct scsi_cmnd *scp, + struct megasas_cmd_fusion *cmd) +{ + u8 fp_possible; + u32 start_lba_lo, start_lba_hi, device_id; + struct MPI2_RAID_SCSI_IO_REQUEST *io_request; + union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc; + struct IO_REQUEST_INFO io_info; + struct fusion_context *fusion; + struct MR_FW_RAID_MAP_ALL *local_map_ptr; + + device_id = MEGASAS_DEV_INDEX(instance, scp); + + fusion = instance->ctrl_context; + + io_request = cmd->io_request; + io_request->RaidContext.VirtualDiskTgtId = device_id; + io_request->RaidContext.status = 0; + io_request->RaidContext.exStatus = 0; + + req_desc = (union MEGASAS_REQUEST_DESCRIPTOR_UNION *)cmd->request_desc; + + start_lba_lo = 0; + start_lba_hi = 0; + fp_possible = 0; + + /* + * 6-byte READ(0x08) or WRITE(0x0A) cdb + */ + if (scp->cmd_len == 6) { + io_request->DataLength = (u32) scp->cmnd[4]; + start_lba_lo = ((u32) scp->cmnd[1] << 16) | + ((u32) scp->cmnd[2] << 8) | (u32) scp->cmnd[3]; + + start_lba_lo &= 0x1FFFFF; + } + + /* + * 10-byte READ(0x28) or WRITE(0x2A) cdb + */ + else if (scp->cmd_len == 10) { + io_request->DataLength = (u32) scp->cmnd[8] | + ((u32) scp->cmnd[7] << 8); + start_lba_lo = ((u32) scp->cmnd[2] << 24) | + ((u32) scp->cmnd[3] << 16) | + ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5]; + } + + /* + * 12-byte READ(0xA8) or WRITE(0xAA) cdb + */ + else if (scp->cmd_len == 12) { + io_request->DataLength = ((u32) scp->cmnd[6] << 24) | + ((u32) scp->cmnd[7] << 16) | + ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9]; + start_lba_lo = ((u32) scp->cmnd[2] << 24) | + ((u32) scp->cmnd[3] << 16) | + ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5]; + } + + /* + * 16-byte READ(0x88) or WRITE(0x8A) cdb + */ + else if (scp->cmd_len == 16) { + io_request->DataLength = ((u32) scp->cmnd[10] << 24) | + ((u32) scp->cmnd[11] << 16) | + ((u32) scp->cmnd[12] << 8) | (u32) scp->cmnd[13]; + start_lba_lo = ((u32) scp->cmnd[6] << 24) | + ((u32) scp->cmnd[7] << 16) | + ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9]; + + start_lba_hi = ((u32) scp->cmnd[2] << 24) | + ((u32) scp->cmnd[3] << 16) | + ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5]; + } + + memset(&io_info, 0, sizeof(struct IO_REQUEST_INFO)); + io_info.ldStartBlock = ((u64)start_lba_hi << 32) | start_lba_lo; + io_info.numBlocks = io_request->DataLength; + io_info.ldTgtId = device_id; + + if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) + io_info.isRead = 1; + + local_map_ptr = fusion->ld_map[(instance->map_id & 1)]; + + if ((MR_TargetIdToLdGet(device_id, local_map_ptr) >= + MAX_LOGICAL_DRIVES) || (!fusion->fast_path_io)) { + io_request->RaidContext.regLockFlags = 0; + fp_possible = 0; + } else { + if (MR_BuildRaidContext(&io_info, &io_request->RaidContext, + local_map_ptr)) + fp_possible = io_info.fpOkForIo; + } + + if (fp_possible) { + megasas_set_pd_lba(io_request, scp->cmd_len, &io_info, scp, + local_map_ptr, start_lba_lo); + io_request->DataLength = scsi_bufflen(scp); + io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST; + cmd->request_desc->SCSIIO.RequestFlags = + (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY + << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); + if ((fusion->load_balance_info[device_id].loadBalanceFlag) && + (io_info.isRead)) { + io_info.devHandle = + get_updated_dev_handle( + &fusion->load_balance_info[device_id], + &io_info); + scp->SCp.Status |= MEGASAS_LOAD_BALANCE_FLAG; + } else + scp->SCp.Status &= ~MEGASAS_LOAD_BALANCE_FLAG; + cmd->request_desc->SCSIIO.DevHandle = io_info.devHandle; + io_request->DevHandle = io_info.devHandle; + } else { + io_request->RaidContext.timeoutValue = + local_map_ptr->raidMap.fpPdIoTimeoutSec; + io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST; + io_request->DevHandle = device_id; + cmd->request_desc->SCSIIO.RequestFlags = + (MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO + << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); + } /* Not FP */ +} + +/** + * megasas_build_dcdb_fusion - Prepares IOs to devices + * @instance: Adapter soft state + * @scp: SCSI command + * @cmd: Command to be prepared + * + * Prepares the io_request frame for non-io cmds + */ +static void +megasas_build_dcdb_fusion(struct megasas_instance *instance, + struct scsi_cmnd *scmd, + struct megasas_cmd_fusion *cmd) +{ + u32 device_id; + struct MPI2_RAID_SCSI_IO_REQUEST *io_request; + u16 pd_index = 0; + struct MR_FW_RAID_MAP_ALL *local_map_ptr; + struct fusion_context *fusion = instance->ctrl_context; + + io_request = cmd->io_request; + device_id = MEGASAS_DEV_INDEX(instance, scmd); + pd_index = (scmd->device->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + +scmd->device->id; + local_map_ptr = fusion->ld_map[(instance->map_id & 1)]; + + /* Check if this is a system PD I/O */ + if ((instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) && + (instance->pd_list[pd_index].driveType == TYPE_DISK)) { + io_request->Function = 0; + io_request->DevHandle = + local_map_ptr->raidMap.devHndlInfo[device_id].curDevHdl; + io_request->RaidContext.timeoutValue = + local_map_ptr->raidMap.fpPdIoTimeoutSec; + io_request->RaidContext.regLockFlags = 0; + io_request->RaidContext.regLockRowLBA = 0; + io_request->RaidContext.regLockLength = 0; + io_request->RaidContext.RAIDFlags = + MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD << + MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT; + cmd->request_desc->SCSIIO.RequestFlags = + (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY << + MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); + } else { + io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST; + io_request->DevHandle = device_id; + cmd->request_desc->SCSIIO.RequestFlags = + (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO << + MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); + } + io_request->RaidContext.VirtualDiskTgtId = device_id; + io_request->LUN[0] = scmd->device->lun; + io_request->DataLength = scsi_bufflen(scmd); +} + +/** + * megasas_build_io_fusion - Prepares IOs to devices + * @instance: Adapter soft state + * @scp: SCSI command + * @cmd: Command to be prepared + * + * Invokes helper functions to prepare request frames + * and sets flags appropriate for IO/Non-IO cmd + */ +int +megasas_build_io_fusion(struct megasas_instance *instance, + struct scsi_cmnd *scp, + struct megasas_cmd_fusion *cmd) +{ + u32 device_id, sge_count; + struct MPI2_RAID_SCSI_IO_REQUEST *io_request = cmd->io_request; + + device_id = MEGASAS_DEV_INDEX(instance, scp); + + /* Zero out some fields so they don't get reused */ + io_request->LUN[0] = 0; + io_request->CDB.EEDP32.PrimaryReferenceTag = 0; + io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0; + io_request->EEDPFlags = 0; + io_request->Control = 0; + io_request->EEDPBlockSize = 0; + io_request->IoFlags = 0; + io_request->RaidContext.RAIDFlags = 0; + + memcpy(io_request->CDB.CDB32, scp->cmnd, scp->cmd_len); + /* + * Just the CDB length,rest of the Flags are zero + * This will be modified for FP in build_ldio_fusion + */ + io_request->IoFlags = scp->cmd_len; + + if (megasas_is_ldio(scp)) + megasas_build_ldio_fusion(instance, scp, cmd); + else + megasas_build_dcdb_fusion(instance, scp, cmd); + + /* + * Construct SGL + */ + + sge_count = + megasas_make_sgl_fusion(instance, scp, + (struct MPI25_IEEE_SGE_CHAIN64 *) + &io_request->SGL, cmd); + + if (sge_count > instance->max_num_sge) { + printk(KERN_ERR "megasas: Error. sge_count (0x%x) exceeds " + "max (0x%x) allowed\n", sge_count, + instance->max_num_sge); + return 1; + } + + io_request->RaidContext.numSGE = sge_count; + + io_request->SGLFlags = MPI2_SGE_FLAGS_64_BIT_ADDRESSING; + + if (scp->sc_data_direction == PCI_DMA_TODEVICE) + io_request->Control |= MPI2_SCSIIO_CONTROL_WRITE; + else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) + io_request->Control |= MPI2_SCSIIO_CONTROL_READ; + + io_request->SGLOffset0 = + offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL) / 4; + + io_request->SenseBufferLowAddress = cmd->sense_phys_addr; + io_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE; + + cmd->scmd = scp; + scp->SCp.ptr = (char *)cmd; + + return 0; +} + +union MEGASAS_REQUEST_DESCRIPTOR_UNION * +megasas_get_request_descriptor(struct megasas_instance *instance, u16 index) +{ + u8 *p; + struct fusion_context *fusion; + + if (index >= instance->max_fw_cmds) { + printk(KERN_ERR "megasas: Invalid SMID (0x%x)request for " + "descriptor\n", index); + return NULL; + } + fusion = instance->ctrl_context; + p = fusion->req_frames_desc + +sizeof(union MEGASAS_REQUEST_DESCRIPTOR_UNION) *index; + + return (union MEGASAS_REQUEST_DESCRIPTOR_UNION *)p; +} + +/** + * megasas_build_and_issue_cmd_fusion -Main routine for building and + * issuing non IOCTL cmd + * @instance: Adapter soft state + * @scmd: pointer to scsi cmd from OS + */ +static u32 +megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance, + struct scsi_cmnd *scmd) +{ + struct megasas_cmd_fusion *cmd; + union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc; + u32 index; + struct fusion_context *fusion; + + fusion = instance->ctrl_context; + + cmd = megasas_get_cmd_fusion(instance); + if (!cmd) + return SCSI_MLQUEUE_HOST_BUSY; + + index = cmd->index; + + req_desc = megasas_get_request_descriptor(instance, index-1); + if (!req_desc) + return 1; + + req_desc->Words = 0; + cmd->request_desc = req_desc; + cmd->request_desc->Words = 0; + + if (megasas_build_io_fusion(instance, scmd, cmd)) { + megasas_return_cmd_fusion(instance, cmd); + printk(KERN_ERR "megasas: Error building command.\n"); + cmd->request_desc = NULL; + return 1; + } + + req_desc = cmd->request_desc; + req_desc->SCSIIO.SMID = index; + + if (cmd->io_request->ChainOffset != 0 && + cmd->io_request->ChainOffset != 0xF) + printk(KERN_ERR "megasas: The chain offset value is not " + "correct : %x\n", cmd->io_request->ChainOffset); + + /* + * Issue the command to the FW + */ + atomic_inc(&instance->fw_outstanding); + + instance->instancet->fire_cmd(instance, + req_desc->u.low, req_desc->u.high, + instance->reg_set); + + return 0; +} + +/** + * complete_cmd_fusion - Completes command + * @instance: Adapter soft state + * Completes all commands that is in reply descriptor queue + */ +int +complete_cmd_fusion(struct megasas_instance *instance) +{ + union MPI2_REPLY_DESCRIPTORS_UNION *desc; + struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *reply_desc; + struct MPI2_RAID_SCSI_IO_REQUEST *scsi_io_req; + struct fusion_context *fusion; + struct megasas_cmd *cmd_mfi; + struct megasas_cmd_fusion *cmd_fusion; + u16 smid, num_completed; + u8 reply_descript_type, arm; + u32 status, extStatus, device_id; + union desc_value d_val; + struct LD_LOAD_BALANCE_INFO *lbinfo; + + fusion = instance->ctrl_context; + + if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) + return IRQ_HANDLED; + + desc = fusion->reply_frames_desc; + desc += fusion->last_reply_idx; + + reply_desc = (struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc; + + d_val.word = desc->Words; + + reply_descript_type = reply_desc->ReplyFlags & + MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; + + if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) + return IRQ_NONE; + + d_val.word = desc->Words; + + num_completed = 0; + + while ((d_val.u.low != UINT_MAX) && (d_val.u.high != UINT_MAX)) { + smid = reply_desc->SMID; + + cmd_fusion = fusion->cmd_list[smid - 1]; + + scsi_io_req = + (struct MPI2_RAID_SCSI_IO_REQUEST *) + cmd_fusion->io_request; + + if (cmd_fusion->scmd) + cmd_fusion->scmd->SCp.ptr = NULL; + + status = scsi_io_req->RaidContext.status; + extStatus = scsi_io_req->RaidContext.exStatus; + + switch (scsi_io_req->Function) { + case MPI2_FUNCTION_SCSI_IO_REQUEST: /*Fast Path IO.*/ + /* Update load balancing info */ + device_id = MEGASAS_DEV_INDEX(instance, + cmd_fusion->scmd); + lbinfo = &fusion->load_balance_info[device_id]; + if (cmd_fusion->scmd->SCp.Status & + MEGASAS_LOAD_BALANCE_FLAG) { + arm = lbinfo->raid1DevHandle[0] == + cmd_fusion->io_request->DevHandle ? 0 : + 1; + atomic_dec(&lbinfo->scsi_pending_cmds[arm]); + cmd_fusion->scmd->SCp.Status &= + ~MEGASAS_LOAD_BALANCE_FLAG; + } + if (reply_descript_type == + MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) { + if (megasas_dbg_lvl == 5) + printk(KERN_ERR "\nmegasas: FAST Path " + "IO Success\n"); + } + /* Fall thru and complete IO */ + case MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST: /* LD-IO Path */ + /* Map the FW Cmd Status */ + map_cmd_status(cmd_fusion, status, extStatus); + scsi_dma_unmap(cmd_fusion->scmd); + cmd_fusion->scmd->scsi_done(cmd_fusion->scmd); + scsi_io_req->RaidContext.status = 0; + scsi_io_req->RaidContext.exStatus = 0; + megasas_return_cmd_fusion(instance, cmd_fusion); + atomic_dec(&instance->fw_outstanding); + + break; + case MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST: /*MFI command */ + cmd_mfi = instance->cmd_list[cmd_fusion->sync_cmd_idx]; + megasas_complete_cmd(instance, cmd_mfi, DID_OK); + cmd_fusion->flags = 0; + megasas_return_cmd_fusion(instance, cmd_fusion); + + break; + } + + fusion->last_reply_idx++; + if (fusion->last_reply_idx >= fusion->reply_q_depth) + fusion->last_reply_idx = 0; + + desc->Words = ULLONG_MAX; + num_completed++; + + /* Get the next reply descriptor */ + if (!fusion->last_reply_idx) + desc = fusion->reply_frames_desc; + else + desc++; + + reply_desc = + (struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc; + + d_val.word = desc->Words; + + reply_descript_type = reply_desc->ReplyFlags & + MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; + + if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) + break; + } + + if (!num_completed) + return IRQ_NONE; + + wmb(); + writel(fusion->last_reply_idx, + &instance->reg_set->reply_post_host_index); + + return IRQ_HANDLED; +} + +/** + * megasas_complete_cmd_dpc_fusion - Completes command + * @instance: Adapter soft state + * + * Tasklet to complete cmds + */ +void +megasas_complete_cmd_dpc_fusion(unsigned long instance_addr) +{ + struct megasas_instance *instance = + (struct megasas_instance *)instance_addr; + unsigned long flags; + + /* If we have already declared adapter dead, donot complete cmds */ + spin_lock_irqsave(&instance->hba_lock, flags); + if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) { + spin_unlock_irqrestore(&instance->hba_lock, flags); + return; + } + spin_unlock_irqrestore(&instance->hba_lock, flags); + + spin_lock_irqsave(&instance->completion_lock, flags); + complete_cmd_fusion(instance); + spin_unlock_irqrestore(&instance->completion_lock, flags); +} + +/** + * megasas_isr_fusion - isr entry point + */ +irqreturn_t megasas_isr_fusion(int irq, void *devp) +{ + struct megasas_instance *instance = (struct megasas_instance *)devp; + u32 mfiStatus, fw_state; + + if (!instance->msi_flag) { + mfiStatus = instance->instancet->clear_intr(instance->reg_set); + if (!mfiStatus) + return IRQ_NONE; + } + + /* If we are resetting, bail */ + if (test_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags)) + return IRQ_HANDLED; + + if (!complete_cmd_fusion(instance)) { + /* If we didn't complete any commands, check for FW fault */ + fw_state = instance->instancet->read_fw_status_reg( + instance->reg_set) & MFI_STATE_MASK; + if (fw_state == MFI_STATE_FAULT) + schedule_work(&instance->work_init); + } + + return IRQ_HANDLED; +} + +/** + * build_mpt_mfi_pass_thru - builds a cmd fo MFI Pass thru + * @instance: Adapter soft state + * mfi_cmd: megasas_cmd pointer + * + */ +u8 +build_mpt_mfi_pass_thru(struct megasas_instance *instance, + struct megasas_cmd *mfi_cmd) +{ + struct MPI25_IEEE_SGE_CHAIN64 *mpi25_ieee_chain; + struct MPI2_RAID_SCSI_IO_REQUEST *io_req; + struct megasas_cmd_fusion *cmd; + struct fusion_context *fusion; + struct megasas_header *frame_hdr = &mfi_cmd->frame->hdr; + + cmd = megasas_get_cmd_fusion(instance); + if (!cmd) + return 1; + + /* Save the smid. To be used for returning the cmd */ + mfi_cmd->context.smid = cmd->index; + + cmd->sync_cmd_idx = mfi_cmd->index; + + /* + * For cmds where the flag is set, store the flag and check + * on completion. For cmds with this flag, don't call + * megasas_complete_cmd + */ + + if (frame_hdr->flags & MFI_FRAME_DONT_POST_IN_REPLY_QUEUE) + cmd->flags = MFI_FRAME_DONT_POST_IN_REPLY_QUEUE; + + fusion = instance->ctrl_context; + io_req = cmd->io_request; + mpi25_ieee_chain = + (struct MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL.IeeeChain; + + io_req->Function = MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST; + io_req->SGLOffset0 = offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, + SGL) / 4; + io_req->ChainOffset = fusion->chain_offset_mfi_pthru; + + mpi25_ieee_chain->Address = mfi_cmd->frame_phys_addr; + + mpi25_ieee_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT | + MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR; + + mpi25_ieee_chain->Length = MEGASAS_MAX_SZ_CHAIN_FRAME; + + return 0; +} + +/** + * build_mpt_cmd - Calls helper function to build a cmd MFI Pass thru cmd + * @instance: Adapter soft state + * @cmd: mfi cmd to build + * + */ +union MEGASAS_REQUEST_DESCRIPTOR_UNION * +build_mpt_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) +{ + union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc; + u16 index; + + if (build_mpt_mfi_pass_thru(instance, cmd)) { + printk(KERN_ERR "Couldn't build MFI pass thru cmd\n"); + return NULL; + } + + index = cmd->context.smid; + + req_desc = megasas_get_request_descriptor(instance, index - 1); + + if (!req_desc) + return NULL; + + req_desc->Words = 0; + req_desc->SCSIIO.RequestFlags = (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO << + MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); + + req_desc->SCSIIO.SMID = index; + + return req_desc; +} + +/** + * megasas_issue_dcmd_fusion - Issues a MFI Pass thru cmd + * @instance: Adapter soft state + * @cmd: mfi cmd pointer + * + */ +void +megasas_issue_dcmd_fusion(struct megasas_instance *instance, + struct megasas_cmd *cmd) +{ + union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc; + union desc_value d_val; + + req_desc = build_mpt_cmd(instance, cmd); + if (!req_desc) { + printk(KERN_ERR "Couldn't issue MFI pass thru cmd\n"); + return; + } + d_val.word = req_desc->Words; + + instance->instancet->fire_cmd(instance, req_desc->u.low, + req_desc->u.high, instance->reg_set); +} + +/** + * megasas_release_fusion - Reverses the FW initialization + * @intance: Adapter soft state + */ +void +megasas_release_fusion(struct megasas_instance *instance) +{ + megasas_free_cmds(instance); + megasas_free_cmds_fusion(instance); + + iounmap(instance->reg_set); + + pci_release_selected_regions(instance->pdev, instance->bar); +} + +/** + * megasas_read_fw_status_reg_fusion - returns the current FW status value + * @regs: MFI register set + */ +static u32 +megasas_read_fw_status_reg_fusion(struct megasas_register_set __iomem *regs) +{ + return readl(&(regs)->outbound_scratch_pad); +} + +/** + * megasas_adp_reset_fusion - For controller reset + * @regs: MFI register set + */ +static int +megasas_adp_reset_fusion(struct megasas_instance *instance, + struct megasas_register_set __iomem *regs) +{ + return 0; +} + +/** + * megasas_check_reset_fusion - For controller reset check + * @regs: MFI register set + */ +static int +megasas_check_reset_fusion(struct megasas_instance *instance, + struct megasas_register_set __iomem *regs) +{ + return 0; +} + +/* This function waits for outstanding commands on fusion to complete */ +int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance) +{ + int i, outstanding, retval = 0; + u32 fw_state, wait_time = MEGASAS_RESET_WAIT_TIME; + + for (i = 0; i < wait_time; i++) { + /* Check if firmware is in fault state */ + fw_state = instance->instancet->read_fw_status_reg( + instance->reg_set) & MFI_STATE_MASK; + if (fw_state == MFI_STATE_FAULT) { + printk(KERN_WARNING "megasas: Found FW in FAULT state," + " will reset adapter.\n"); + retval = 1; + goto out; + } + + outstanding = atomic_read(&instance->fw_outstanding); + if (!outstanding) + goto out; + + if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { + printk(KERN_NOTICE "megasas: [%2d]waiting for %d " + "commands to complete\n", i, outstanding); + megasas_complete_cmd_dpc_fusion( + (unsigned long)instance); + } + msleep(1000); + } + + if (atomic_read(&instance->fw_outstanding)) { + printk("megaraid_sas: pending commands remain after waiting, " + "will reset adapter.\n"); + retval = 1; + } +out: + return retval; +} + +void megasas_reset_reply_desc(struct megasas_instance *instance) +{ + int i; + struct fusion_context *fusion; + union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc; + + fusion = instance->ctrl_context; + fusion->last_reply_idx = 0; + reply_desc = fusion->reply_frames_desc; + for (i = 0 ; i < fusion->reply_q_depth; i++, reply_desc++) + reply_desc->Words = ULLONG_MAX; +} + +/* Core fusion reset function */ +int megasas_reset_fusion(struct Scsi_Host *shost) +{ + int retval = SUCCESS, i, j, retry = 0; + struct megasas_instance *instance; + struct megasas_cmd_fusion *cmd_fusion; + struct fusion_context *fusion; + struct megasas_cmd *cmd_mfi; + union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc; + u32 host_diag, abs_state; + + instance = (struct megasas_instance *)shost->hostdata; + fusion = instance->ctrl_context; + + mutex_lock(&instance->reset_mutex); + set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); + instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT; + instance->instancet->disable_intr(instance->reg_set); + msleep(1000); + + if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) { + printk(KERN_WARNING "megaraid_sas: Hardware critical error, " + "returning FAILED.\n"); + retval = FAILED; + goto out; + } + + /* First try waiting for commands to complete */ + if (megasas_wait_for_outstanding_fusion(instance)) { + printk(KERN_WARNING "megaraid_sas: resetting fusion " + "adapter.\n"); + /* Now return commands back to the OS */ + for (i = 0 ; i < instance->max_fw_cmds; i++) { + cmd_fusion = fusion->cmd_list[i]; + if (cmd_fusion->scmd) { + scsi_dma_unmap(cmd_fusion->scmd); + cmd_fusion->scmd->result = (DID_RESET << 16); + cmd_fusion->scmd->scsi_done(cmd_fusion->scmd); + megasas_return_cmd_fusion(instance, cmd_fusion); + atomic_dec(&instance->fw_outstanding); + } + } + + if (instance->disableOnlineCtrlReset == 1) { + /* Reset not supported, kill adapter */ + printk(KERN_WARNING "megaraid_sas: Reset not supported" + ", killing adapter.\n"); + megaraid_sas_kill_hba(instance); + instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR; + retval = FAILED; + goto out; + } + + /* Now try to reset the chip */ + for (i = 0; i < MEGASAS_FUSION_MAX_RESET_TRIES; i++) { + writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, + &instance->reg_set->fusion_seq_offset); + writel(MPI2_WRSEQ_1ST_KEY_VALUE, + &instance->reg_set->fusion_seq_offset); + writel(MPI2_WRSEQ_2ND_KEY_VALUE, + &instance->reg_set->fusion_seq_offset); + writel(MPI2_WRSEQ_3RD_KEY_VALUE, + &instance->reg_set->fusion_seq_offset); + writel(MPI2_WRSEQ_4TH_KEY_VALUE, + &instance->reg_set->fusion_seq_offset); + writel(MPI2_WRSEQ_5TH_KEY_VALUE, + &instance->reg_set->fusion_seq_offset); + writel(MPI2_WRSEQ_6TH_KEY_VALUE, + &instance->reg_set->fusion_seq_offset); + + /* Check that the diag write enable (DRWE) bit is on */ + host_diag = readl(&instance->reg_set->fusion_host_diag); + while (!(host_diag & HOST_DIAG_WRITE_ENABLE)) { + msleep(100); + host_diag = + readl(&instance->reg_set->fusion_host_diag); + if (retry++ == 100) { + printk(KERN_WARNING "megaraid_sas: " + "Host diag unlock failed!\n"); + break; + } + } + if (!(host_diag & HOST_DIAG_WRITE_ENABLE)) + continue; + + /* Send chip reset command */ + writel(host_diag | HOST_DIAG_RESET_ADAPTER, + &instance->reg_set->fusion_host_diag); + msleep(3000); + + /* Make sure reset adapter bit is cleared */ + host_diag = readl(&instance->reg_set->fusion_host_diag); + retry = 0; + while (host_diag & HOST_DIAG_RESET_ADAPTER) { + msleep(100); + host_diag = + readl(&instance->reg_set->fusion_host_diag); + if (retry++ == 1000) { + printk(KERN_WARNING "megaraid_sas: " + "Diag reset adapter never " + "cleared!\n"); + break; + } + } + if (host_diag & HOST_DIAG_RESET_ADAPTER) + continue; + + abs_state = + instance->instancet->read_fw_status_reg( + instance->reg_set); + retry = 0; + + while ((abs_state <= MFI_STATE_FW_INIT) && + (retry++ < 1000)) { + msleep(100); + abs_state = + instance->instancet->read_fw_status_reg( + instance->reg_set); + } + if (abs_state <= MFI_STATE_FW_INIT) { + printk(KERN_WARNING "megaraid_sas: firmware " + "state < MFI_STATE_FW_INIT, state = " + "0x%x\n", abs_state); + continue; + } + + /* Wait for FW to become ready */ + if (megasas_transition_to_ready(instance)) { + printk(KERN_WARNING "megaraid_sas: Failed to " + "transition controller to ready.\n"); + continue; + } + + megasas_reset_reply_desc(instance); + if (megasas_ioc_init_fusion(instance)) { + printk(KERN_WARNING "megaraid_sas: " + "megasas_ioc_init_fusion() failed!\n"); + continue; + } + + instance->instancet->enable_intr(instance->reg_set); + instance->adprecovery = MEGASAS_HBA_OPERATIONAL; + + /* Re-fire management commands */ + for (j = 0 ; j < instance->max_fw_cmds; j++) { + cmd_fusion = fusion->cmd_list[j]; + if (cmd_fusion->sync_cmd_idx != + (u32)ULONG_MAX) { + cmd_mfi = + instance-> + cmd_list[cmd_fusion->sync_cmd_idx]; + if (cmd_mfi->frame->dcmd.opcode == + MR_DCMD_LD_MAP_GET_INFO) { + megasas_return_cmd(instance, + cmd_mfi); + megasas_return_cmd_fusion( + instance, cmd_fusion); + } else { + req_desc = + megasas_get_request_descriptor( + instance, + cmd_mfi->context.smid + -1); + if (!req_desc) + printk(KERN_WARNING + "req_desc NULL" + "\n"); + else { + instance->instancet-> + fire_cmd(instance, + req_desc-> + u.low, + req_desc-> + u.high, + instance-> + reg_set); + } + } + } + } + + /* Reset load balance info */ + memset(fusion->load_balance_info, 0, + sizeof(struct LD_LOAD_BALANCE_INFO) + *MAX_LOGICAL_DRIVES); + + if (!megasas_get_map_info(instance)) + megasas_sync_map_info(instance); + + /* Adapter reset completed successfully */ + printk(KERN_WARNING "megaraid_sas: Reset " + "successful.\n"); + retval = SUCCESS; + goto out; + } + /* Reset failed, kill the adapter */ + printk(KERN_WARNING "megaraid_sas: Reset failed, killing " + "adapter.\n"); + megaraid_sas_kill_hba(instance); + retval = FAILED; + } else { + instance->instancet->enable_intr(instance->reg_set); + instance->adprecovery = MEGASAS_HBA_OPERATIONAL; + } +out: + clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); + mutex_unlock(&instance->reset_mutex); + return retval; +} + +/* Fusion OCR work queue */ +void megasas_fusion_ocr_wq(struct work_struct *work) +{ + struct megasas_instance *instance = + container_of(work, struct megasas_instance, work_init); + + megasas_reset_fusion(instance->host); +} + +struct megasas_instance_template megasas_instance_template_fusion = { + .fire_cmd = megasas_fire_cmd_fusion, + .enable_intr = megasas_enable_intr_fusion, + .disable_intr = megasas_disable_intr_fusion, + .clear_intr = megasas_clear_intr_fusion, + .read_fw_status_reg = megasas_read_fw_status_reg_fusion, + .adp_reset = megasas_adp_reset_fusion, + .check_reset = megasas_check_reset_fusion, + .service_isr = megasas_isr_fusion, + .tasklet = megasas_complete_cmd_dpc_fusion, + .init_adapter = megasas_init_adapter_fusion, + .build_and_issue_cmd = megasas_build_and_issue_cmd_fusion, + .issue_dcmd = megasas_issue_dcmd_fusion, +}; diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h new file mode 100644 index 000000000000..82b577a72c8b --- /dev/null +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h @@ -0,0 +1,695 @@ +/* + * Linux MegaRAID driver for SAS based RAID controllers + * + * Copyright (c) 2009-2011 LSI Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * FILE: megaraid_sas_fusion.h + * + * Authors: LSI Corporation + * Manoj Jose + * Sumant Patro + * + * Send feedback to: + * + * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035 + * ATTN: Linuxraid + */ + +#ifndef _MEGARAID_SAS_FUSION_H_ +#define _MEGARAID_SAS_FUSION_H_ + +/* Fusion defines */ +#define MEGASAS_MAX_SZ_CHAIN_FRAME 1024 +#define MFI_FUSION_ENABLE_INTERRUPT_MASK (0x00000009) +#define MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE 256 +#define MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST 0xF0 +#define MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST 0xF1 +#define MEGASAS_LOAD_BALANCE_FLAG 0x1 +#define MEGASAS_DCMD_MBOX_PEND_FLAG 0x1 +#define HOST_DIAG_WRITE_ENABLE 0x80 +#define HOST_DIAG_RESET_ADAPTER 0x4 +#define MEGASAS_FUSION_MAX_RESET_TRIES 3 + +/* T10 PI defines */ +#define MR_PROT_INFO_TYPE_CONTROLLER 0x8 +#define MEGASAS_SCSI_VARIABLE_LENGTH_CMD 0x7f +#define MEGASAS_SCSI_SERVICE_ACTION_READ32 0x9 +#define MEGASAS_SCSI_SERVICE_ACTION_WRITE32 0xB +#define MEGASAS_SCSI_ADDL_CDB_LEN 0x18 +#define MEGASAS_RD_WR_PROTECT_CHECK_ALL 0x20 +#define MEGASAS_RD_WR_PROTECT_CHECK_NONE 0x60 +#define MEGASAS_EEDPBLOCKSIZE 512 + +/* + * Raid context flags + */ + +#define MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT 0x4 +#define MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_MASK 0x30 +enum MR_RAID_FLAGS_IO_SUB_TYPE { + MR_RAID_FLAGS_IO_SUB_TYPE_NONE = 0, + MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD = 1, +}; + +/* + * Request descriptor types + */ +#define MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO 0x7 +#define MEGASAS_REQ_DESCRIPT_FLAGS_MFA 0x1 + +#define MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT 1 + +#define MEGASAS_FP_CMD_LEN 16 +#define MEGASAS_FUSION_IN_RESET 0 + +/* + * Raid Context structure which describes MegaRAID specific IO Paramenters + * This resides at offset 0x60 where the SGL normally starts in MPT IO Frames + */ + +struct RAID_CONTEXT { + u16 resvd0; + u16 timeoutValue; + u8 regLockFlags; + u8 resvd1; + u16 VirtualDiskTgtId; + u64 regLockRowLBA; + u32 regLockLength; + u16 nextLMId; + u8 exStatus; + u8 status; + u8 RAIDFlags; + u8 numSGE; + u16 configSeqNum; + u8 spanArm; + u8 resvd2[3]; +}; + +#define RAID_CTX_SPANARM_ARM_SHIFT (0) +#define RAID_CTX_SPANARM_ARM_MASK (0x1f) + +#define RAID_CTX_SPANARM_SPAN_SHIFT (5) +#define RAID_CTX_SPANARM_SPAN_MASK (0xE0) + +/* + * define region lock types + */ +enum REGION_TYPE { + REGION_TYPE_UNUSED = 0, + REGION_TYPE_SHARED_READ = 1, + REGION_TYPE_SHARED_WRITE = 2, + REGION_TYPE_EXCLUSIVE = 3, +}; + +/* MPI2 defines */ +#define MPI2_FUNCTION_IOC_INIT (0x02) /* IOC Init */ +#define MPI2_WHOINIT_HOST_DRIVER (0x04) +#define MPI2_VERSION_MAJOR (0x02) +#define MPI2_VERSION_MINOR (0x00) +#define MPI2_VERSION_MAJOR_MASK (0xFF00) +#define MPI2_VERSION_MAJOR_SHIFT (8) +#define MPI2_VERSION_MINOR_MASK (0x00FF) +#define MPI2_VERSION_MINOR_SHIFT (0) +#define MPI2_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) | \ + MPI2_VERSION_MINOR) +#define MPI2_HEADER_VERSION_UNIT (0x10) +#define MPI2_HEADER_VERSION_DEV (0x00) +#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00) +#define MPI2_HEADER_VERSION_UNIT_SHIFT (8) +#define MPI2_HEADER_VERSION_DEV_MASK (0x00FF) +#define MPI2_HEADER_VERSION_DEV_SHIFT (0) +#define MPI2_HEADER_VERSION ((MPI2_HEADER_VERSION_UNIT << 8) | \ + MPI2_HEADER_VERSION_DEV) +#define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR (0x03) +#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG (0x8000) +#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG (0x0400) +#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP (0x0003) +#define MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG (0x0200) +#define MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD (0x0100) +#define MPI2_SCSIIO_EEDPFLAGS_INSERT_OP (0x0004) +#define MPI2_FUNCTION_SCSI_IO_REQUEST (0x00) /* SCSI IO */ +#define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY (0x06) +#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO (0x00) +#define MPI2_SGE_FLAGS_64_BIT_ADDRESSING (0x02) +#define MPI2_SCSIIO_CONTROL_WRITE (0x01000000) +#define MPI2_SCSIIO_CONTROL_READ (0x02000000) +#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK (0x0E) +#define MPI2_RPY_DESCRIPT_FLAGS_UNUSED (0x0F) +#define MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS (0x00) +#define MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK (0x0F) +#define MPI2_WRSEQ_FLUSH_KEY_VALUE (0x0) +#define MPI2_WRITE_SEQUENCE_OFFSET (0x00000004) +#define MPI2_WRSEQ_1ST_KEY_VALUE (0xF) +#define MPI2_WRSEQ_2ND_KEY_VALUE (0x4) +#define MPI2_WRSEQ_3RD_KEY_VALUE (0xB) +#define MPI2_WRSEQ_4TH_KEY_VALUE (0x2) +#define MPI2_WRSEQ_5TH_KEY_VALUE (0x7) +#define MPI2_WRSEQ_6TH_KEY_VALUE (0xD) + +struct MPI25_IEEE_SGE_CHAIN64 { + u64 Address; + u32 Length; + u16 Reserved1; + u8 NextChainOffset; + u8 Flags; +}; + +struct MPI2_SGE_SIMPLE_UNION { + u32 FlagsLength; + union { + u32 Address32; + u64 Address64; + } u; +}; + +struct MPI2_SCSI_IO_CDB_EEDP32 { + u8 CDB[20]; /* 0x00 */ + u32 PrimaryReferenceTag; /* 0x14 */ + u16 PrimaryApplicationTag; /* 0x18 */ + u16 PrimaryApplicationTagMask; /* 0x1A */ + u32 TransferLength; /* 0x1C */ +}; + +struct MPI2_SGE_CHAIN_UNION { + u16 Length; + u8 NextChainOffset; + u8 Flags; + union { + u32 Address32; + u64 Address64; + } u; +}; + +struct MPI2_IEEE_SGE_SIMPLE32 { + u32 Address; + u32 FlagsLength; +}; + +struct MPI2_IEEE_SGE_CHAIN32 { + u32 Address; + u32 FlagsLength; +}; + +struct MPI2_IEEE_SGE_SIMPLE64 { + u64 Address; + u32 Length; + u16 Reserved1; + u8 Reserved2; + u8 Flags; +}; + +struct MPI2_IEEE_SGE_CHAIN64 { + u64 Address; + u32 Length; + u16 Reserved1; + u8 Reserved2; + u8 Flags; +}; + +union MPI2_IEEE_SGE_SIMPLE_UNION { + struct MPI2_IEEE_SGE_SIMPLE32 Simple32; + struct MPI2_IEEE_SGE_SIMPLE64 Simple64; +}; + +union MPI2_IEEE_SGE_CHAIN_UNION { + struct MPI2_IEEE_SGE_CHAIN32 Chain32; + struct MPI2_IEEE_SGE_CHAIN64 Chain64; +}; + +union MPI2_SGE_IO_UNION { + struct MPI2_SGE_SIMPLE_UNION MpiSimple; + struct MPI2_SGE_CHAIN_UNION MpiChain; + union MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple; + union MPI2_IEEE_SGE_CHAIN_UNION IeeeChain; +}; + +union MPI2_SCSI_IO_CDB_UNION { + u8 CDB32[32]; + struct MPI2_SCSI_IO_CDB_EEDP32 EEDP32; + struct MPI2_SGE_SIMPLE_UNION SGE; +}; + +/* + * RAID SCSI IO Request Message + * Total SGE count will be one less than _MPI2_SCSI_IO_REQUEST + */ +struct MPI2_RAID_SCSI_IO_REQUEST { + u16 DevHandle; /* 0x00 */ + u8 ChainOffset; /* 0x02 */ + u8 Function; /* 0x03 */ + u16 Reserved1; /* 0x04 */ + u8 Reserved2; /* 0x06 */ + u8 MsgFlags; /* 0x07 */ + u8 VP_ID; /* 0x08 */ + u8 VF_ID; /* 0x09 */ + u16 Reserved3; /* 0x0A */ + u32 SenseBufferLowAddress; /* 0x0C */ + u16 SGLFlags; /* 0x10 */ + u8 SenseBufferLength; /* 0x12 */ + u8 Reserved4; /* 0x13 */ + u8 SGLOffset0; /* 0x14 */ + u8 SGLOffset1; /* 0x15 */ + u8 SGLOffset2; /* 0x16 */ + u8 SGLOffset3; /* 0x17 */ + u32 SkipCount; /* 0x18 */ + u32 DataLength; /* 0x1C */ + u32 BidirectionalDataLength; /* 0x20 */ + u16 IoFlags; /* 0x24 */ + u16 EEDPFlags; /* 0x26 */ + u32 EEDPBlockSize; /* 0x28 */ + u32 SecondaryReferenceTag; /* 0x2C */ + u16 SecondaryApplicationTag; /* 0x30 */ + u16 ApplicationTagTranslationMask; /* 0x32 */ + u8 LUN[8]; /* 0x34 */ + u32 Control; /* 0x3C */ + union MPI2_SCSI_IO_CDB_UNION CDB; /* 0x40 */ + struct RAID_CONTEXT RaidContext; /* 0x60 */ + union MPI2_SGE_IO_UNION SGL; /* 0x80 */ +}; + +/* + * MPT RAID MFA IO Descriptor. + */ +struct MEGASAS_RAID_MFA_IO_REQUEST_DESCRIPTOR { + u32 RequestFlags:8; + u32 MessageAddress1:24; /* bits 31:8*/ + u32 MessageAddress2; /* bits 61:32 */ +}; + +/* Default Request Descriptor */ +struct MPI2_DEFAULT_REQUEST_DESCRIPTOR { + u8 RequestFlags; /* 0x00 */ + u8 MSIxIndex; /* 0x01 */ + u16 SMID; /* 0x02 */ + u16 LMID; /* 0x04 */ + u16 DescriptorTypeDependent; /* 0x06 */ +}; + +/* High Priority Request Descriptor */ +struct MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR { + u8 RequestFlags; /* 0x00 */ + u8 MSIxIndex; /* 0x01 */ + u16 SMID; /* 0x02 */ + u16 LMID; /* 0x04 */ + u16 Reserved1; /* 0x06 */ +}; + +/* SCSI IO Request Descriptor */ +struct MPI2_SCSI_IO_REQUEST_DESCRIPTOR { + u8 RequestFlags; /* 0x00 */ + u8 MSIxIndex; /* 0x01 */ + u16 SMID; /* 0x02 */ + u16 LMID; /* 0x04 */ + u16 DevHandle; /* 0x06 */ +}; + +/* SCSI Target Request Descriptor */ +struct MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR { + u8 RequestFlags; /* 0x00 */ + u8 MSIxIndex; /* 0x01 */ + u16 SMID; /* 0x02 */ + u16 LMID; /* 0x04 */ + u16 IoIndex; /* 0x06 */ +}; + +/* RAID Accelerator Request Descriptor */ +struct MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR { + u8 RequestFlags; /* 0x00 */ + u8 MSIxIndex; /* 0x01 */ + u16 SMID; /* 0x02 */ + u16 LMID; /* 0x04 */ + u16 Reserved; /* 0x06 */ +}; + +/* union of Request Descriptors */ +union MEGASAS_REQUEST_DESCRIPTOR_UNION { + struct MPI2_DEFAULT_REQUEST_DESCRIPTOR Default; + struct MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR HighPriority; + struct MPI2_SCSI_IO_REQUEST_DESCRIPTOR SCSIIO; + struct MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR SCSITarget; + struct MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR RAIDAccelerator; + struct MEGASAS_RAID_MFA_IO_REQUEST_DESCRIPTOR MFAIo; + union { + struct { + u32 low; + u32 high; + } u; + u64 Words; + }; +}; + +/* Default Reply Descriptor */ +struct MPI2_DEFAULT_REPLY_DESCRIPTOR { + u8 ReplyFlags; /* 0x00 */ + u8 MSIxIndex; /* 0x01 */ + u16 DescriptorTypeDependent1; /* 0x02 */ + u32 DescriptorTypeDependent2; /* 0x04 */ +}; + +/* Address Reply Descriptor */ +struct MPI2_ADDRESS_REPLY_DESCRIPTOR { + u8 ReplyFlags; /* 0x00 */ + u8 MSIxIndex; /* 0x01 */ + u16 SMID; /* 0x02 */ + u32 ReplyFrameAddress; /* 0x04 */ +}; + +/* SCSI IO Success Reply Descriptor */ +struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR { + u8 ReplyFlags; /* 0x00 */ + u8 MSIxIndex; /* 0x01 */ + u16 SMID; /* 0x02 */ + u16 TaskTag; /* 0x04 */ + u16 Reserved1; /* 0x06 */ +}; + +/* TargetAssist Success Reply Descriptor */ +struct MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR { + u8 ReplyFlags; /* 0x00 */ + u8 MSIxIndex; /* 0x01 */ + u16 SMID; /* 0x02 */ + u8 SequenceNumber; /* 0x04 */ + u8 Reserved1; /* 0x05 */ + u16 IoIndex; /* 0x06 */ +}; + +/* Target Command Buffer Reply Descriptor */ +struct MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR { + u8 ReplyFlags; /* 0x00 */ + u8 MSIxIndex; /* 0x01 */ + u8 VP_ID; /* 0x02 */ + u8 Flags; /* 0x03 */ + u16 InitiatorDevHandle; /* 0x04 */ + u16 IoIndex; /* 0x06 */ +}; + +/* RAID Accelerator Success Reply Descriptor */ +struct MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR { + u8 ReplyFlags; /* 0x00 */ + u8 MSIxIndex; /* 0x01 */ + u16 SMID; /* 0x02 */ + u32 Reserved; /* 0x04 */ +}; + +/* union of Reply Descriptors */ +union MPI2_REPLY_DESCRIPTORS_UNION { + struct MPI2_DEFAULT_REPLY_DESCRIPTOR Default; + struct MPI2_ADDRESS_REPLY_DESCRIPTOR AddressReply; + struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR SCSIIOSuccess; + struct MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR TargetAssistSuccess; + struct MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR TargetCommandBuffer; + struct MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR + RAIDAcceleratorSuccess; + u64 Words; +}; + +/* IOCInit Request message */ +struct MPI2_IOC_INIT_REQUEST { + u8 WhoInit; /* 0x00 */ + u8 Reserved1; /* 0x01 */ + u8 ChainOffset; /* 0x02 */ + u8 Function; /* 0x03 */ + u16 Reserved2; /* 0x04 */ + u8 Reserved3; /* 0x06 */ + u8 MsgFlags; /* 0x07 */ + u8 VP_ID; /* 0x08 */ + u8 VF_ID; /* 0x09 */ + u16 Reserved4; /* 0x0A */ + u16 MsgVersion; /* 0x0C */ + u16 HeaderVersion; /* 0x0E */ + u32 Reserved5; /* 0x10 */ + u16 Reserved6; /* 0x14 */ + u8 Reserved7; /* 0x16 */ + u8 HostMSIxVectors; /* 0x17 */ + u16 Reserved8; /* 0x18 */ + u16 SystemRequestFrameSize; /* 0x1A */ + u16 ReplyDescriptorPostQueueDepth; /* 0x1C */ + u16 ReplyFreeQueueDepth; /* 0x1E */ + u32 SenseBufferAddressHigh; /* 0x20 */ + u32 SystemReplyAddressHigh; /* 0x24 */ + u64 SystemRequestFrameBaseAddress; /* 0x28 */ + u64 ReplyDescriptorPostQueueAddress;/* 0x30 */ + u64 ReplyFreeQueueAddress; /* 0x38 */ + u64 TimeStamp; /* 0x40 */ +}; + +/* mrpriv defines */ +#define MR_PD_INVALID 0xFFFF +#define MAX_SPAN_DEPTH 8 +#define MAX_RAIDMAP_SPAN_DEPTH (MAX_SPAN_DEPTH) +#define MAX_ROW_SIZE 32 +#define MAX_RAIDMAP_ROW_SIZE (MAX_ROW_SIZE) +#define MAX_LOGICAL_DRIVES 64 +#define MAX_RAIDMAP_LOGICAL_DRIVES (MAX_LOGICAL_DRIVES) +#define MAX_RAIDMAP_VIEWS (MAX_LOGICAL_DRIVES) +#define MAX_ARRAYS 128 +#define MAX_RAIDMAP_ARRAYS (MAX_ARRAYS) +#define MAX_PHYSICAL_DEVICES 256 +#define MAX_RAIDMAP_PHYSICAL_DEVICES (MAX_PHYSICAL_DEVICES) +#define MR_DCMD_LD_MAP_GET_INFO 0x0300e101 + +struct MR_DEV_HANDLE_INFO { + u16 curDevHdl; + u8 validHandles; + u8 reserved; + u16 devHandle[2]; +}; + +struct MR_ARRAY_INFO { + u16 pd[MAX_RAIDMAP_ROW_SIZE]; +}; + +struct MR_QUAD_ELEMENT { + u64 logStart; + u64 logEnd; + u64 offsetInSpan; + u32 diff; + u32 reserved1; +}; + +struct MR_SPAN_INFO { + u32 noElements; + u32 reserved1; + struct MR_QUAD_ELEMENT quad[MAX_RAIDMAP_SPAN_DEPTH]; +}; + +struct MR_LD_SPAN { + u64 startBlk; + u64 numBlks; + u16 arrayRef; + u8 reserved[6]; +}; + +struct MR_SPAN_BLOCK_INFO { + u64 num_rows; + struct MR_LD_SPAN span; + struct MR_SPAN_INFO block_span_info; +}; + +struct MR_LD_RAID { + struct { + u32 fpCapable:1; + u32 reserved5:3; + u32 ldPiMode:4; + u32 pdPiMode:4; + u32 encryptionType:8; + u32 fpWriteCapable:1; + u32 fpReadCapable:1; + u32 fpWriteAcrossStripe:1; + u32 fpReadAcrossStripe:1; + u32 reserved4:8; + } capability; + u32 reserved6; + u64 size; + u8 spanDepth; + u8 level; + u8 stripeShift; + u8 rowSize; + u8 rowDataSize; + u8 writeMode; + u8 PRL; + u8 SRL; + u16 targetId; + u8 ldState; + u8 regTypeReqOnWrite; + u8 modFactor; + u8 reserved2[1]; + u16 seqNum; + + struct { + u32 ldSyncRequired:1; + u32 reserved:31; + } flags; + + u8 reserved3[0x5C]; +}; + +struct MR_LD_SPAN_MAP { + struct MR_LD_RAID ldRaid; + u8 dataArmMap[MAX_RAIDMAP_ROW_SIZE]; + struct MR_SPAN_BLOCK_INFO spanBlock[MAX_RAIDMAP_SPAN_DEPTH]; +}; + +struct MR_FW_RAID_MAP { + u32 totalSize; + union { + struct { + u32 maxLd; + u32 maxSpanDepth; + u32 maxRowSize; + u32 maxPdCount; + u32 maxArrays; + } validationInfo; + u32 version[5]; + u32 reserved1[5]; + }; + + u32 ldCount; + u32 Reserved1; + u8 ldTgtIdToLd[MAX_RAIDMAP_LOGICAL_DRIVES+ + MAX_RAIDMAP_VIEWS]; + u8 fpPdIoTimeoutSec; + u8 reserved2[7]; + struct MR_ARRAY_INFO arMapInfo[MAX_RAIDMAP_ARRAYS]; + struct MR_DEV_HANDLE_INFO devHndlInfo[MAX_RAIDMAP_PHYSICAL_DEVICES]; + struct MR_LD_SPAN_MAP ldSpanMap[1]; +}; + +struct IO_REQUEST_INFO { + u64 ldStartBlock; + u32 numBlocks; + u16 ldTgtId; + u8 isRead; + u16 devHandle; + u64 pdBlock; + u8 fpOkForIo; +}; + +struct MR_LD_TARGET_SYNC { + u8 targetId; + u8 reserved; + u16 seqNum; +}; + +#define IEEE_SGE_FLAGS_ADDR_MASK (0x03) +#define IEEE_SGE_FLAGS_SYSTEM_ADDR (0x00) +#define IEEE_SGE_FLAGS_IOCDDR_ADDR (0x01) +#define IEEE_SGE_FLAGS_IOCPLB_ADDR (0x02) +#define IEEE_SGE_FLAGS_IOCPLBNTA_ADDR (0x03) +#define IEEE_SGE_FLAGS_CHAIN_ELEMENT (0x80) +#define IEEE_SGE_FLAGS_END_OF_LIST (0x40) + +struct megasas_register_set; +struct megasas_instance; + +union desc_word { + u64 word; + struct { + u32 low; + u32 high; + } u; +}; + +struct megasas_cmd_fusion { + struct MPI2_RAID_SCSI_IO_REQUEST *io_request; + dma_addr_t io_request_phys_addr; + + union MPI2_SGE_IO_UNION *sg_frame; + dma_addr_t sg_frame_phys_addr; + + u8 *sense; + dma_addr_t sense_phys_addr; + + struct list_head list; + struct scsi_cmnd *scmd; + struct megasas_instance *instance; + + u8 retry_for_fw_reset; + union MEGASAS_REQUEST_DESCRIPTOR_UNION *request_desc; + + /* + * Context for a MFI frame. + * Used to get the mfi cmd from list when a MFI cmd is completed + */ + u32 sync_cmd_idx; + u32 index; + u8 flags; +}; + +struct LD_LOAD_BALANCE_INFO { + u8 loadBalanceFlag; + u8 reserved1; + u16 raid1DevHandle[2]; + atomic_t scsi_pending_cmds[2]; + u64 last_accessed_block[2]; +}; + +struct MR_FW_RAID_MAP_ALL { + struct MR_FW_RAID_MAP raidMap; + struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES - 1]; +} __attribute__ ((packed)); + +struct fusion_context { + struct megasas_cmd_fusion **cmd_list; + struct list_head cmd_pool; + + spinlock_t cmd_pool_lock; + + dma_addr_t req_frames_desc_phys; + u8 *req_frames_desc; + + struct dma_pool *io_request_frames_pool; + dma_addr_t io_request_frames_phys; + u8 *io_request_frames; + + struct dma_pool *sg_dma_pool; + struct dma_pool *sense_dma_pool; + + dma_addr_t reply_frames_desc_phys; + union MPI2_REPLY_DESCRIPTORS_UNION *reply_frames_desc; + struct dma_pool *reply_frames_desc_pool; + + u16 last_reply_idx; + + u32 reply_q_depth; + u32 request_alloc_sz; + u32 reply_alloc_sz; + u32 io_frames_alloc_sz; + + u16 max_sge_in_main_msg; + u16 max_sge_in_chain; + + u8 chain_offset_io_request; + u8 chain_offset_mfi_pthru; + + struct MR_FW_RAID_MAP_ALL *ld_map[2]; + dma_addr_t ld_map_phys[2]; + + u32 map_sz; + u8 fast_path_io; + struct LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES]; +}; + +union desc_value { + u64 word; + struct { + u32 low; + u32 high; + } u; +}; + +#endif /* _MEGARAID_SAS_FUSION_H_ */ -- cgit v1.2.3-59-g8ed1b From 5f7bb3a439ce51ae8b92ca1dc93b91712224b69a Mon Sep 17 00:00:00 2001 From: adam radford Date: Tue, 14 Dec 2010 19:11:56 -0800 Subject: [SCSI] megaraid_sas: Documentation update The following patch updates the Documentation/scsi/ChangeLog.megaraid_sas file. Signed-off-by: Adam Radford Signed-off-by: James Bottomley --- Documentation/scsi/ChangeLog.megaraid_sas | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Documentation/scsi/ChangeLog.megaraid_sas b/Documentation/scsi/ChangeLog.megaraid_sas index 00301ed9c371..b64d10d221ec 100644 --- a/Documentation/scsi/ChangeLog.megaraid_sas +++ b/Documentation/scsi/ChangeLog.megaraid_sas @@ -1,3 +1,25 @@ +Release Date : Tues. Dec 14, 2010 17:00:00 PST 2010 - + (emaild-id:megaraidlinux@lsi.com) + Adam Radford +Current Version : 00.00.05.29-rc1 +Old Version : 00.00.04.31-rc1 + 1. Rename megaraid_sas.c to megaraid_sas_base.c. + 2. Update GPL headers. + 3. Add MSI-X support and 'msix_disable' module parameter. + 4. Use lowest memory bar (for SR-IOV VF support). + 5. Add struct megasas_instance_temlate changes, and change all code to use + new instance entries: + + irqreturn_t (*service_isr )(int irq, void *devp); + void (*tasklet)(unsigned long); + u32 (*init_adapter)(struct megasas_instance *); + u32 (*build_and_issue_cmd) (struct megasas_instance *, + struct scsi_cmnd *); + void (*issue_dcmd) (struct megasas_instance *instance, + struct megasas_cmd *cmd); + + 6. Add code to support MegaRAID 9265/9285 controllers device id (0x5b). +------------------------------------------------------------------------------- 1 Release Date : Thur. May 03, 2010 09:12:45 PST 2009 - (emaild-id:megaraidlinux@lsi.com) Bo Yang -- cgit v1.2.3-59-g8ed1b From 579d12b58abb4bd1161728f0a4a2524258ecf0a3 Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Tue, 21 Dec 2010 16:00:14 -0800 Subject: [SCSI] qla2xxx: Added support for quiescence mode for ISP82xx. Support is added for quiescence mode. This feature is for P3P adapters. Any of the functions can put the firmware into quiescence state. All the others have to ack that request. During quiescence mode current commands are processed and all the new incoming I/Os are blocked. Loop resync is performed after firmware comes out of quiescence state. Signed-off-by: Saurav Kashyap Signed-off-by: Madhuranath Iyengar Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_def.h | 3 + drivers/scsi/qla2xxx/qla_gbl.h | 4 ++ drivers/scsi/qla2xxx/qla_init.c | 67 +++++++++++++++++++- drivers/scsi/qla2xxx/qla_nx.c | 132 +++++++++++++++++++++++++++++++++++++++- drivers/scsi/qla2xxx/qla_os.c | 24 +++++++- 5 files changed, 224 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 9ce539d4557e..6168628bd6b9 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2425,6 +2425,8 @@ struct qla_hw_data { uint32_t disable_msix_handshake :1; uint32_t fcp_prio_enabled :1; uint32_t fw_hung :1; + uint32_t quiesce_owner:1; + /* 29 bits */ } flags; /* This spinlock is used to protect "io transactions", you must @@ -2863,6 +2865,7 @@ typedef struct scsi_qla_host { #define ISP_UNRECOVERABLE 17 #define FCOE_CTX_RESET_NEEDED 18 /* Initiate FCoE context reset */ #define MPI_RESET_NEEDED 19 /* Initiate MPI FW reset */ +#define ISP_QUIESCE_NEEDED 20 /* Driver need some quiescence */ uint32_t device_flags; #define SWITCH_FOUND BIT_0 diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 9382a816c133..1370f05ae330 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -36,6 +36,7 @@ extern int qla2x00_load_risc(struct scsi_qla_host *, uint32_t *); extern int qla24xx_load_risc(scsi_qla_host_t *, uint32_t *); extern int qla81xx_load_risc(scsi_qla_host_t *, uint32_t *); +extern int qla2x00_perform_loop_resync(scsi_qla_host_t *); extern int qla2x00_loop_resync(scsi_qla_host_t *); extern int qla2x00_fabric_login(scsi_qla_host_t *, fc_port_t *, uint16_t *); @@ -45,6 +46,7 @@ extern void qla2x00_update_fcports(scsi_qla_host_t *); extern int qla2x00_abort_isp(scsi_qla_host_t *); extern void qla2x00_abort_isp_cleanup(scsi_qla_host_t *); +extern void qla82xx_quiescent_state_cleanup(scsi_qla_host_t *); extern void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *); @@ -549,9 +551,11 @@ extern void qla82xx_rom_unlock(struct qla_hw_data *); /* ISP 8021 IDC */ extern void qla82xx_clear_drv_active(struct qla_hw_data *); +extern uint32_t qla82xx_wait_for_state_change(scsi_qla_host_t *, uint32_t); extern int qla82xx_idc_lock(struct qla_hw_data *); extern void qla82xx_idc_unlock(struct qla_hw_data *); extern int qla82xx_device_state_handler(scsi_qla_host_t *); +extern void qla82xx_clear_qsnt_ready(scsi_qla_host_t *); extern void qla2x00_set_model_info(scsi_qla_host_t *, uint8_t *, size_t, char *); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 259f51137493..6f7cf3970383 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3844,6 +3844,37 @@ qla2x00_loop_resync(scsi_qla_host_t *vha) return (rval); } +/* +* qla2x00_perform_loop_resync +* Description: This function will set the appropriate flags and call +* qla2x00_loop_resync. If successful loop will be resynced +* Arguments : scsi_qla_host_t pointer +* returm : Success or Failure +*/ + +int qla2x00_perform_loop_resync(scsi_qla_host_t *ha) +{ + int32_t rval = 0; + + if (!test_and_set_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags)) { + /*Configure the flags so that resync happens properly*/ + atomic_set(&ha->loop_down_timer, 0); + if (!(ha->device_flags & DFLG_NO_CABLE)) { + atomic_set(&ha->loop_state, LOOP_UP); + set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); + set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags); + set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); + + rval = qla2x00_loop_resync(ha); + } else + atomic_set(&ha->loop_state, LOOP_DEAD); + + clear_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags); + } + + return rval; +} + void qla2x00_update_fcports(scsi_qla_host_t *base_vha) { @@ -3871,11 +3902,43 @@ qla2x00_update_fcports(scsi_qla_host_t *base_vha) spin_unlock_irqrestore(&ha->vport_slock, flags); } +/* +* qla82xx_quiescent_state_cleanup +* Description: This function will block the new I/Os +* Its not aborting any I/Os as context +* is not destroyed during quiescence +* Arguments: scsi_qla_host_t +* return : void +*/ +void +qla82xx_quiescent_state_cleanup(scsi_qla_host_t *vha) +{ + struct qla_hw_data *ha = vha->hw; + struct scsi_qla_host *vp; + + qla_printk(KERN_INFO, ha, + "Performing ISP error recovery - ha= %p.\n", ha); + + atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); + if (atomic_read(&vha->loop_state) != LOOP_DOWN) { + atomic_set(&vha->loop_state, LOOP_DOWN); + qla2x00_mark_all_devices_lost(vha, 0); + list_for_each_entry(vp, &ha->vp_list, list) + qla2x00_mark_all_devices_lost(vha, 0); + } else { + if (!atomic_read(&vha->loop_down_timer)) + atomic_set(&vha->loop_down_timer, + LOOP_DOWN_TIME); + } + /* Wait for pending cmds to complete */ + qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST); +} + void qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; - struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev); + struct scsi_qla_host *vp; unsigned long flags; vha->flags.online = 0; @@ -3896,7 +3959,7 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha) qla2x00_mark_all_devices_lost(vha, 0); spin_lock_irqsave(&ha->vport_slock, flags); - list_for_each_entry(vp, &base_vha->hw->vp_list, list) { + list_for_each_entry(vp, &ha->vp_list, list) { atomic_inc(&vp->vref_count); spin_unlock_irqrestore(&ha->vport_slock, flags); diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index ae2acacc0003..9175e847b93a 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -2343,6 +2343,17 @@ qla82xx_set_qsnt_ready(struct qla_hw_data *ha) qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, qsnt_state); } +void +qla82xx_clear_qsnt_ready(scsi_qla_host_t *vha) +{ + struct qla_hw_data *ha = vha->hw; + uint32_t qsnt_state; + + qsnt_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE); + qsnt_state &= ~(QLA82XX_DRVST_QSNT_RDY << (ha->portnum * 4)); + qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, qsnt_state); +} + static int qla82xx_load_fw(scsi_qla_host_t *vha) { @@ -3261,6 +3272,104 @@ dev_ready: return QLA_SUCCESS; } +/* +* qla82xx_need_qsnt_handler +* Code to start quiescence sequence +* +* Note: +* IDC lock must be held upon entry +* +* Return: void +*/ + +static void +qla82xx_need_qsnt_handler(scsi_qla_host_t *vha) +{ + struct qla_hw_data *ha = vha->hw; + uint32_t dev_state, drv_state, drv_active; + unsigned long reset_timeout; + + if (vha->flags.online) { + /*Block any further I/O and wait for pending cmnds to complete*/ + qla82xx_quiescent_state_cleanup(vha); + } + + /* Set the quiescence ready bit */ + qla82xx_set_qsnt_ready(ha); + + /*wait for 30 secs for other functions to ack */ + reset_timeout = jiffies + (30 * HZ); + + drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE); + drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); + /* Its 2 that is written when qsnt is acked, moving one bit */ + drv_active = drv_active << 0x01; + + while (drv_state != drv_active) { + + if (time_after_eq(jiffies, reset_timeout)) { + /* quiescence timeout, other functions didn't ack + * changing the state to DEV_READY + */ + qla_printk(KERN_INFO, ha, + "%s: QUIESCENT TIMEOUT\n", QLA2XXX_DRIVER_NAME); + qla_printk(KERN_INFO, ha, + "DRV_ACTIVE:%d DRV_STATE:%d\n", drv_active, + drv_state); + qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, + QLA82XX_DEV_READY); + qla_printk(KERN_INFO, ha, + "HW State: DEV_READY\n"); + qla82xx_idc_unlock(ha); + qla2x00_perform_loop_resync(vha); + qla82xx_idc_lock(ha); + + qla82xx_clear_qsnt_ready(vha); + return; + } + + qla82xx_idc_unlock(ha); + msleep(1000); + qla82xx_idc_lock(ha); + + drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE); + drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); + drv_active = drv_active << 0x01; + } + dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); + /* everyone acked so set the state to DEV_QUIESCENCE */ + if (dev_state == QLA82XX_DEV_NEED_QUIESCENT) { + qla_printk(KERN_INFO, ha, "HW State: DEV_QUIESCENT\n"); + qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_QUIESCENT); + } +} + +/* +* qla82xx_wait_for_state_change +* Wait for device state to change from given current state +* +* Note: +* IDC lock must not be held upon entry +* +* Return: +* Changed device state. +*/ +uint32_t +qla82xx_wait_for_state_change(scsi_qla_host_t *vha, uint32_t curr_state) +{ + struct qla_hw_data *ha = vha->hw; + uint32_t dev_state; + + do { + msleep(1000); + qla82xx_idc_lock(ha); + dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); + qla82xx_idc_unlock(ha); + } while (dev_state == curr_state); + + return dev_state; +} + static void qla82xx_dev_failed_handler(scsi_qla_host_t *vha) { @@ -3443,11 +3552,25 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha) qla82xx_need_reset_handler(vha); break; case QLA82XX_DEV_NEED_QUIESCENT: - qla82xx_set_qsnt_ready(ha); + qla82xx_need_qsnt_handler(vha); + /* Reset timeout value after quiescence handler */ + dev_init_timeout = jiffies + (ha->nx_dev_init_timeout\ + * HZ); + break; case QLA82XX_DEV_QUIESCENT: + /* Owner will exit and other will wait for the state + * to get changed + */ + if (ha->flags.quiesce_owner) + goto exit; + qla82xx_idc_unlock(ha); msleep(1000); qla82xx_idc_lock(ha); + + /* Reset timeout value after quiescence handler */ + dev_init_timeout = jiffies + (ha->nx_dev_init_timeout\ + * HZ); break; case QLA82XX_DEV_FAILED: qla82xx_dev_failed_handler(vha); @@ -3490,6 +3613,13 @@ void qla82xx_watchdog(scsi_qla_host_t *vha) &ha->mbx_cmd_flags)) complete(&ha->mbx_intr_comp); } + } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT && + !test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags)) { + DEBUG(qla_printk(KERN_INFO, ha, + "scsi(%ld) %s - detected quiescence needed\n", + vha->host_no, __func__)); + set_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags); + qla2xxx_wake_dpc(vha); } else { qla82xx_check_fw_alive(vha); } diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 2c0876c81a3f..df2c1e7ab652 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -3386,6 +3386,21 @@ qla2x00_do_dpc(void *data) clear_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags); } + if (test_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags)) { + DEBUG(printk(KERN_INFO "scsi(%ld): dpc: sched " + "qla2x00_quiesce_needed ha = %p\n", + base_vha->host_no, ha)); + qla82xx_device_state_handler(base_vha); + clear_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags); + if (!ha->flags.quiesce_owner) { + qla2x00_perform_loop_resync(base_vha); + + qla82xx_idc_lock(ha); + qla82xx_clear_qsnt_ready(base_vha); + qla82xx_idc_unlock(ha); + } + } + if (test_and_clear_bit(RESET_MARKER_NEEDED, &base_vha->dpc_flags) && (!(test_and_set_bit(RESET_ACTIVE, &base_vha->dpc_flags)))) { @@ -3589,13 +3604,16 @@ qla2x00_timer(scsi_qla_host_t *vha) return; } - if (IS_QLA82XX(ha)) - qla82xx_watchdog(vha); - /* Hardware read to raise pending EEH errors during mailbox waits. */ if (!pci_channel_offline(ha->pdev)) pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w); + if (IS_QLA82XX(ha)) { + if (test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags)) + start_dpc++; + qla82xx_watchdog(vha); + } + /* Loop down handler. */ if (atomic_read(&vha->loop_down_timer) > 0 && !(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) -- cgit v1.2.3-59-g8ed1b From 8ae598d02517af967685a671303c4ed10cded3c4 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 21 Dec 2010 16:00:15 -0800 Subject: [SCSI] qla2xxx: list cursors are not null This is just a cleanup. The unneeded NULL check annoys static checkers because we already derefenced it and the we check it and then (if it's not the _safe() version) we dereference it again without checking. And the static checker is all, "Wah? Is it null or not?" Signed-off-by: Dan Carpenter Signed-off-by: Madhuranath Iyengar Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 2 +- drivers/scsi/qla2xxx/qla_os.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 6f7cf3970383..e9b800e72559 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3888,7 +3888,7 @@ qla2x00_update_fcports(scsi_qla_host_t *base_vha) list_for_each_entry(vha, &base_vha->hw->vp_list, list) { atomic_inc(&vha->vref_count); list_for_each_entry(fcport, &vha->vp_fcports, list) { - if (fcport && fcport->drport && + if (fcport->drport && atomic_read(&fcport->state) != FCS_UNCONFIGURED) { spin_unlock_irqrestore(&ha->vport_slock, flags); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index df2c1e7ab652..1814df868526 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2371,7 +2371,7 @@ qla2x00_remove_one(struct pci_dev *pdev) list_for_each_entry(vha, &ha->vp_list, list) { atomic_inc(&vha->vref_count); - if (vha && vha->fc_vport) { + if (vha->fc_vport) { spin_unlock_irqrestore(&ha->vport_slock, flags); fc_vport_terminate(vha->fc_vport); -- cgit v1.2.3-59-g8ed1b From ff8073fffc708a4959c2dd159c834f2516ce9703 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Tue, 21 Dec 2010 16:00:16 -0800 Subject: [SCSI] qla2xxx: Populate FCP_PRIO location for no *FLT* case Signed-off-by: Andrew Vasquez Signed-off-by: Madhuranath Iyengar Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_sup.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 76de9574b385..22070621206c 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -669,6 +669,13 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) def = 1; else if (IS_QLA81XX(ha)) def = 2; + + /* Assign FCP prio region since older adapters may not have FLT, or + FCP prio region in it's FLT. + */ + ha->flt_region_fcp_prio = ha->flags.port0 ? + fcp_prio_cfg0[def] : fcp_prio_cfg1[def]; + ha->flt_region_flt = flt_addr; wptr = (uint16_t *)req->ring; flt = (struct qla_flt_header *)req->ring; @@ -696,10 +703,6 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr) goto no_flash_data; } - /* Assign FCP prio region since older FLT's may not have it */ - ha->flt_region_fcp_prio = ha->flags.port0 ? - fcp_prio_cfg0[def] : fcp_prio_cfg1[def]; - loc = locations[1]; cnt = le16_to_cpu(flt->length) / sizeof(struct qla_flt_region); for ( ; cnt; cnt--, region++) { -- cgit v1.2.3-59-g8ed1b From 4052bd57234f119cef13b8997fcc852e2b2ce992 Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Tue, 21 Dec 2010 16:00:17 -0800 Subject: [SCSI] qla2xxx: Fixed zero test on new_config in qla2x00_process_loopback(). Fixed the incorrect zero test on array new_config[]. Signed-off-by: Joe Carnuccio Signed-off-by: Madhuranath Iyengar Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_bsg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 31a4121a2be1..6146d392eeb5 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -753,7 +753,7 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job) command_sent = INT_DEF_LB_LOOPBACK_CMD; rval = qla2x00_loopback_test(vha, &elreq, response); - if (new_config[1]) { + if (new_config[0]) { /* Revert back to original port config * Also clear internal loopback */ -- cgit v1.2.3-59-g8ed1b From 21090cbe95189d4ce6135fc8fec2f416b3eb227f Mon Sep 17 00:00:00 2001 From: Madhuranath Iyengar Date: Tue, 21 Dec 2010 16:00:18 -0800 Subject: [SCSI] qla2xxx: Update FCP priority information to firmware before sending IOs The FCP priority info was not being updated properly in certain situations. Here are the changes that needs to be done to take care of this issue: 1. No need to check fcport->state for FCS_UNCONFIGURED in qla24xx_update_fcport_fcp_prio(), since an invalid loop id check is already performed which is sufficient. 2. Add the missing qla24xx_update_fcport_fcp_prio() function call within qla2x00_update_fcport() function, so that the priority info is updated on every port addition or change. 3. Perform proper adapter types checking. 4. Other changes, associated with DEBUG/printk's and parameter passing. Signed-off-by: Saurav Kashyap Signed-off-by: Andrew Vasquez Signed-off-by: Giridhar Malavali Signed-off-by: Madhuranath Iyengar Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_bsg.c | 2 +- drivers/scsi/qla2xxx/qla_gbl.h | 1 + drivers/scsi/qla2xxx/qla_init.c | 18 +++++++++--------- drivers/scsi/qla2xxx/qla_mbx.c | 2 +- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 6146d392eeb5..10942fc9808d 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -103,7 +103,7 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job) bsg_job->reply->reply_payload_rcv_len = 0; - if (!IS_QLA24XX_TYPE(ha) || !IS_QLA25XX(ha)) { + if (!(IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha))) { ret = -EINVAL; goto exit_fcp_prio_cfg; } diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 1370f05ae330..c228d248cf17 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -70,6 +70,7 @@ extern void qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *, extern void qla2x00_async_tm_cmd_done(struct scsi_qla_host *, fc_port_t *, struct srb_iocb *); extern void *qla2x00_alloc_iocbs(struct scsi_qla_host *, srb_t *); +extern int qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *, fc_port_t *); extern fc_port_t * qla2x00_alloc_fcport(scsi_qla_host_t *, gfp_t ); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index e9b800e72559..c8ca25a8f2c2 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -2928,6 +2928,7 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT); qla2x00_iidma_fcport(vha, fcport); + qla24xx_update_fcport_fcp_prio(vha, fcport); qla2x00_reg_remote_port(vha, fcport); atomic_set(&fcport->state, FCS_ONLINE); } @@ -5473,7 +5474,7 @@ qla81xx_update_fw_options(scsi_qla_host_t *vha) * the tag (priority) value is returned. * * Input: - * ha = adapter block po + * vha = scsi host structure pointer. * fcport = port structure pointer. * * Return: @@ -5567,7 +5568,7 @@ qla24xx_get_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport) * Activates fcp priority for the logged in fc port * * Input: - * ha = adapter block pointer. + * vha = scsi host structure pointer. * fcp = port structure pointer. * * Return: @@ -5577,25 +5578,24 @@ qla24xx_get_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport) * Kernel context. */ int -qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *ha, fc_port_t *fcport) +qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *vha, fc_port_t *fcport) { int ret; uint8_t priority; uint16_t mb[5]; - if (atomic_read(&fcport->state) == FCS_UNCONFIGURED || - fcport->port_type != FCT_TARGET || - fcport->loop_id == FC_NO_LOOP_ID) + if (fcport->port_type != FCT_TARGET || + fcport->loop_id == FC_NO_LOOP_ID) return QLA_FUNCTION_FAILED; - priority = qla24xx_get_fcp_prio(ha, fcport); - ret = qla24xx_set_fcp_prio(ha, fcport->loop_id, priority, mb); + priority = qla24xx_get_fcp_prio(vha, fcport); + ret = qla24xx_set_fcp_prio(vha, fcport->loop_id, priority, mb); if (ret == QLA_SUCCESS) fcport->fcp_prio = priority; else DEBUG2(printk(KERN_WARNING "scsi(%ld): Unable to activate fcp priority, " - " ret=0x%x\n", ha->host_no, ret)); + " ret=0x%x\n", vha->host_no, ret)); return ret; } diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index effd8a1403d9..04d6cfc2e919 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -4125,7 +4125,7 @@ qla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t priority, return QLA_FUNCTION_FAILED; DEBUG11(printk(KERN_INFO - "%s(%ld): entered.\n", __func__, ha->host_no)); + "%s(%ld): entered.\n", __func__, vha->host_no)); mcp->mb[0] = MBC_PORT_PARAMS; mcp->mb[1] = loop_id; -- cgit v1.2.3-59-g8ed1b From c9e8fd5cfb7de50139a8aa0f70f9fe03311cdd01 Mon Sep 17 00:00:00 2001 From: Madhuranath Iyengar Date: Tue, 21 Dec 2010 16:00:19 -0800 Subject: [SCSI] qla2xxx: Fix for memory wedge on fw halt for ISP82XX Signed-off-by: Swapnil Nagle Signed-off-by: Karen Higgins Signed-off-by: Madhuranath Iyengar Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_nx.c | 44 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 9175e847b93a..6ea5e98b850b 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -1079,11 +1079,55 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha) /* Halt all the indiviual PEGs and other blocks of the ISP */ qla82xx_rom_lock(ha); + + /* mask all niu interrupts */ + qla82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x40, 0xff); + /* disable xge rx/tx */ + qla82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x70000, 0x00); + /* disable xg1 rx/tx */ + qla82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x80000, 0x00); + + /* halt sre */ + val = qla82xx_rd_32(ha, QLA82XX_CRB_SRE + 0x1000); + qla82xx_wr_32(ha, QLA82XX_CRB_SRE + 0x1000, val & (~(0x1))); + + /* halt epg */ + qla82xx_wr_32(ha, QLA82XX_CRB_EPG + 0x1300, 0x1); + + /* halt timers */ + qla82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x0, 0x0); + qla82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x8, 0x0); + qla82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x10, 0x0); + qla82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x18, 0x0); + qla82xx_wr_32(ha, QLA82XX_CRB_TIMER + 0x100, 0x0); + + /* halt pegs */ + qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x3c, 1); + qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_1 + 0x3c, 1); + qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_2 + 0x3c, 1); + qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_3 + 0x3c, 1); + qla82xx_wr_32(ha, QLA82XX_CRB_PEG_NET_4 + 0x3c, 1); + + /* big hammer */ + msleep(1000); if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) /* don't reset CAM block on reset */ qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xfeffffff); else qla82xx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xffffffff); + + /* reset ms */ + val = qla82xx_rd_32(ha, QLA82XX_CRB_QDR_NET + 0xe4); + val |= (1 << 1); + qla82xx_wr_32(ha, QLA82XX_CRB_QDR_NET + 0xe4, val); + msleep(20); + + /* unreset ms */ + val = qla82xx_rd_32(ha, QLA82XX_CRB_QDR_NET + 0xe4); + val &= ~(1 << 1); + qla82xx_wr_32(ha, QLA82XX_CRB_QDR_NET + 0xe4, val); + msleep(20); + qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK)); /* Read the signature value from the flash. -- cgit v1.2.3-59-g8ed1b From 10fbb7dd36eb3014fe4b928e596d89e036ee6210 Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Tue, 21 Dec 2010 16:00:20 -0800 Subject: [SCSI] qla2xxx: Code cleanup to remove unwanted comments and code. Signed-off-by: Giridhar Malavali Signed-off-by: Lalit Chandivade Signed-off-by: Madhuranath Iyengar Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_nx.c | 36 ------------------------------------ drivers/scsi/qla2xxx/qla_nx.h | 2 -- 2 files changed, 38 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 6ea5e98b850b..22b0d781c75a 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -1253,25 +1253,6 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha) return 0; } -static int -qla82xx_check_for_bad_spd(struct qla_hw_data *ha) -{ - u32 val = 0; - val = qla82xx_rd_32(ha, BOOT_LOADER_DIMM_STATUS); - val &= QLA82XX_BOOT_LOADER_MN_ISSUE; - if (val & QLA82XX_PEG_TUNE_MN_SPD_ZEROED) { - qla_printk(KERN_INFO, ha, - "Memory DIMM SPD not programmed. " - " Assumed valid.\n"); - return 1; - } else if (val) { - qla_printk(KERN_INFO, ha, - "Memory DIMM type incorrect.Info:%08X.\n", val); - return 2; - } - return 0; -} - static int qla82xx_pci_mem_write_2M(struct qla_hw_data *ha, u64 off, void *data, int size) @@ -1337,11 +1318,6 @@ qla82xx_pci_mem_write_2M(struct qla_hw_data *ha, word[startword+1] |= tmpw >> (sz[0] * 8); } - /* - * don't lock here - write_wx gets the lock if each time - * write_lock_irqsave(&adapter->adapter_lock, flags); - * netxen_nic_pci_change_crbwindow_128M(adapter, 0); - */ for (i = 0; i < loop; i++) { temp = off8 + (i << shift_amount); qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_LO, temp); @@ -1443,12 +1419,6 @@ qla82xx_pci_mem_read_2M(struct qla_hw_data *ha, off0[1] = 0; sz[1] = size - sz[0]; - /* - * don't lock here - write_wx gets the lock if each time - * write_lock_irqsave(&adapter->adapter_lock, flags); - * netxen_nic_pci_change_crbwindow_128M(adapter, 0); - */ - for (i = 0; i < loop; i++) { temp = off8 + (i << shift_amount); qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_LO, temp); @@ -1481,11 +1451,6 @@ qla82xx_pci_mem_read_2M(struct qla_hw_data *ha, } } - /* - * netxen_nic_pci_change_crbwindow_128M(adapter, 1); - * write_unlock_irqrestore(&adapter->adapter_lock, flags); - */ - if (j >= MAX_CTL_CHECK) return -1; @@ -1916,7 +1881,6 @@ qla82xx_check_cmdpeg_state(struct qla_hw_data *ha) qla_printk(KERN_INFO, ha, "Cmd Peg initialization failed: 0x%x.\n", val); - qla82xx_check_for_bad_spd(ha); val = qla82xx_rd_32(ha, QLA82XX_ROMUSB_GLB_PEGTUNE_DONE); read_lock(&ha->hw_lock); qla82xx_wr_32(ha, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED); diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h index 51ec0c5380e8..ed5883f1778a 100644 --- a/drivers/scsi/qla2xxx/qla_nx.h +++ b/drivers/scsi/qla2xxx/qla_nx.h @@ -523,8 +523,6 @@ # define QLA82XX_CAM_RAM_BASE (QLA82XX_CRB_CAM + 0x02000) # define QLA82XX_CAM_RAM(reg) (QLA82XX_CAM_RAM_BASE + (reg)) -#define QLA82XX_PEG_TUNE_MN_SPD_ZEROED 0x80000000 -#define QLA82XX_BOOT_LOADER_MN_ISSUE 0xff00ffff #define QLA82XX_PORT_MODE_ADDR (QLA82XX_CAM_RAM(0x24)) #define QLA82XX_PEG_HALT_STATUS1 (QLA82XX_CAM_RAM(0xa8)) #define QLA82XX_PEG_HALT_STATUS2 (QLA82XX_CAM_RAM(0xac)) -- cgit v1.2.3-59-g8ed1b From 794a5691147652387f4a2ffa890c5c1983e38849 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Tue, 21 Dec 2010 16:00:21 -0800 Subject: [SCSI] qla2xxx: Add sysfs node for displaying board temperature. Signed-off-by: Andrew Vasquez Signed-off-by: Madhuranath Iyengar Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 27 +++++++++++++++++ drivers/scsi/qla2xxx/qla_def.h | 3 +- drivers/scsi/qla2xxx/qla_gbl.h | 2 ++ drivers/scsi/qla2xxx/qla_init.c | 1 + drivers/scsi/qla2xxx/qla_mbx.c | 65 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 97 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index bc8194f74625..44578b56ad0a 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -1308,6 +1308,31 @@ qla2x00_fabric_param_show(struct device *dev, struct device_attribute *attr, return snprintf(buf, PAGE_SIZE, "%d\n", vha->hw->switch_cap); } +static ssize_t +qla2x00_thermal_temp_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); + int rval = QLA_FUNCTION_FAILED; + uint16_t temp, frac; + + if (!vha->hw->flags.thermal_supported) + return snprintf(buf, PAGE_SIZE, "\n"); + + temp = frac = 0; + if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) || + test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags)) + DEBUG2_3_11(printk(KERN_WARNING + "%s(%ld): isp reset in progress.\n", + __func__, vha->host_no)); + else if (!vha->hw->flags.eeh_busy) + rval = qla2x00_get_thermal_temp(vha, &temp, &frac); + if (rval != QLA_SUCCESS) + temp = frac = 0; + + return snprintf(buf, PAGE_SIZE, "%d.%02d\n", temp, frac); +} + static ssize_t qla2x00_fw_state_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -1366,6 +1391,7 @@ static DEVICE_ATTR(vn_port_mac_address, S_IRUGO, qla2x00_vn_port_mac_address_show, NULL); static DEVICE_ATTR(fabric_param, S_IRUGO, qla2x00_fabric_param_show, NULL); static DEVICE_ATTR(fw_state, S_IRUGO, qla2x00_fw_state_show, NULL); +static DEVICE_ATTR(thermal_temp, S_IRUGO, qla2x00_thermal_temp_show, NULL); struct device_attribute *qla2x00_host_attrs[] = { &dev_attr_driver_version, @@ -1394,6 +1420,7 @@ struct device_attribute *qla2x00_host_attrs[] = { &dev_attr_fabric_param, &dev_attr_fw_state, &dev_attr_optrom_gold_fw_version, + &dev_attr_thermal_temp, NULL, }; diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 6168628bd6b9..ccfc8e78be21 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2426,7 +2426,8 @@ struct qla_hw_data { uint32_t fcp_prio_enabled :1; uint32_t fw_hung :1; uint32_t quiesce_owner:1; - /* 29 bits */ + uint32_t thermal_supported:1; + /* 26 bits */ } flags; /* This spinlock is used to protect "io transactions", you must diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index c228d248cf17..39c4bdda5e3e 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -53,6 +53,8 @@ extern void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *); extern void qla2x00_alloc_fw_dump(scsi_qla_host_t *); extern void qla2x00_try_to_stop_firmware(scsi_qla_host_t *); +extern int qla2x00_get_thermal_temp(scsi_qla_host_t *, uint16_t *, uint16_t *); + extern void qla84xx_put_chip(struct scsi_qla_host *); extern int qla2x00_async_login(struct scsi_qla_host *, fc_port_t *, diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index c8ca25a8f2c2..d0a0dc9d6d36 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -498,6 +498,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) vha->flags.reset_active = 0; ha->flags.pci_channel_io_perm_failure = 0; ha->flags.eeh_busy = 0; + ha->flags.thermal_supported = 1; atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); atomic_set(&vha->loop_state, LOOP_DOWN); vha->device_flags = DFLG_NO_CABLE; diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 04d6cfc2e919..e473e9fb363c 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -4159,6 +4159,71 @@ qla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t priority, return rval; } +int +qla2x00_get_thermal_temp(scsi_qla_host_t *vha, uint16_t *temp, uint16_t *frac) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + struct qla_hw_data *ha = vha->hw; + + DEBUG11(printk(KERN_INFO "%s(%ld): entered.\n", __func__, ha->host_no)); + + /* High bits. */ + mcp->mb[0] = MBC_READ_SFP; + mcp->mb[1] = 0x98; + mcp->mb[2] = 0; + mcp->mb[3] = 0; + mcp->mb[6] = 0; + mcp->mb[7] = 0; + mcp->mb[8] = 1; + mcp->mb[9] = 0x01; + mcp->mb[10] = BIT_13|BIT_0; + mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->tov = MBX_TOV_SECONDS; + mcp->flags = 0; + rval = qla2x00_mailbox_command(vha, mcp); + if (rval != QLA_SUCCESS) { + DEBUG2_3_11(printk(KERN_WARNING + "%s(%ld): failed=%x (%x).\n", __func__, + vha->host_no, rval, mcp->mb[0])); + ha->flags.thermal_supported = 0; + goto fail; + } + *temp = mcp->mb[1] & 0xFF; + + /* Low bits. */ + mcp->mb[0] = MBC_READ_SFP; + mcp->mb[1] = 0x98; + mcp->mb[2] = 0; + mcp->mb[3] = 0; + mcp->mb[6] = 0; + mcp->mb[7] = 0; + mcp->mb[8] = 1; + mcp->mb[9] = 0x10; + mcp->mb[10] = BIT_13|BIT_0; + mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_1|MBX_0; + mcp->tov = MBX_TOV_SECONDS; + mcp->flags = 0; + rval = qla2x00_mailbox_command(vha, mcp); + if (rval != QLA_SUCCESS) { + DEBUG2_3_11(printk(KERN_WARNING + "%s(%ld): failed=%x (%x).\n", __func__, + vha->host_no, rval, mcp->mb[0])); + ha->flags.thermal_supported = 0; + goto fail; + } + *frac = ((mcp->mb[1] & 0xFF) >> 6) * 25; + + if (rval == QLA_SUCCESS) + DEBUG11(printk(KERN_INFO + "%s(%ld): done.\n", __func__, ha->host_no)); +fail: + return rval; +} + int qla82xx_mbx_intr_enable(scsi_qla_host_t *vha) { -- cgit v1.2.3-59-g8ed1b From f2019cb117f29ffaff961b5f6d5b3148d473de1d Mon Sep 17 00:00:00 2001 From: Joe Carnuccio Date: Tue, 21 Dec 2010 16:00:22 -0800 Subject: [SCSI] qla2xxx: Remove redundant module parameter permission bits For driver module parameters that have permission bits set to (S_IRUGO|S_IRUSR), remove the second term since it is already included in the first term. S_IRUGO comes defined as (S_IRUSR|S_IRGRP|S_IROTH). Signed-off-by: Joe Carnuccio Signed-off-by: Madhuranath Iyengar Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 1814df868526..51e944fafdc6 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -37,12 +37,12 @@ static struct kmem_cache *srb_cachep; static struct kmem_cache *ctx_cachep; int ql2xlogintimeout = 20; -module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR); +module_param(ql2xlogintimeout, int, S_IRUGO); MODULE_PARM_DESC(ql2xlogintimeout, "Login timeout value in seconds."); int qlport_down_retry; -module_param(qlport_down_retry, int, S_IRUGO|S_IRUSR); +module_param(qlport_down_retry, int, S_IRUGO); MODULE_PARM_DESC(qlport_down_retry, "Maximum number of command retries to a port that returns " "a PORT-DOWN status."); @@ -55,12 +55,12 @@ MODULE_PARM_DESC(ql2xplogiabsentdevice, "Default is 0 - no PLOGI. 1 - perfom PLOGI."); int ql2xloginretrycount = 0; -module_param(ql2xloginretrycount, int, S_IRUGO|S_IRUSR); +module_param(ql2xloginretrycount, int, S_IRUGO); MODULE_PARM_DESC(ql2xloginretrycount, "Specify an alternate value for the NVRAM login retry count."); int ql2xallocfwdump = 1; -module_param(ql2xallocfwdump, int, S_IRUGO|S_IRUSR); +module_param(ql2xallocfwdump, int, S_IRUGO); MODULE_PARM_DESC(ql2xallocfwdump, "Option to enable allocation of memory for a firmware dump " "during HBA initialization. Memory allocation requirements " @@ -73,7 +73,7 @@ MODULE_PARM_DESC(ql2xextended_error_logging, "Default is 0 - no logging. 1 - log errors."); int ql2xshiftctondsd = 6; -module_param(ql2xshiftctondsd, int, S_IRUGO|S_IRUSR); +module_param(ql2xshiftctondsd, int, S_IRUGO); MODULE_PARM_DESC(ql2xshiftctondsd, "Set to control shifting of command type processing " "based on total number of SG elements."); @@ -81,7 +81,7 @@ MODULE_PARM_DESC(ql2xshiftctondsd, static void qla2x00_free_device(scsi_qla_host_t *); int ql2xfdmienable=1; -module_param(ql2xfdmienable, int, S_IRUGO|S_IRUSR); +module_param(ql2xfdmienable, int, S_IRUGO); MODULE_PARM_DESC(ql2xfdmienable, "Enables FDMI registrations. " "0 - no FDMI. Default is 1 - perform FDMI."); @@ -106,27 +106,27 @@ MODULE_PARM_DESC(ql2xenablehba_err_chk, " Default is 0 - Error isolation disabled, 1 - Enable it"); int ql2xiidmaenable=1; -module_param(ql2xiidmaenable, int, S_IRUGO|S_IRUSR); +module_param(ql2xiidmaenable, int, S_IRUGO); MODULE_PARM_DESC(ql2xiidmaenable, "Enables iIDMA settings " "Default is 1 - perform iIDMA. 0 - no iIDMA."); int ql2xmaxqueues = 1; -module_param(ql2xmaxqueues, int, S_IRUGO|S_IRUSR); +module_param(ql2xmaxqueues, int, S_IRUGO); MODULE_PARM_DESC(ql2xmaxqueues, "Enables MQ settings " "Default is 1 for single queue. Set it to number " "of queues in MQ mode."); int ql2xmultique_tag; -module_param(ql2xmultique_tag, int, S_IRUGO|S_IRUSR); +module_param(ql2xmultique_tag, int, S_IRUGO); MODULE_PARM_DESC(ql2xmultique_tag, "Enables CPU affinity settings for the driver " "Default is 0 for no affinity of request and response IO. " "Set it to 1 to turn on the cpu affinity."); int ql2xfwloadbin; -module_param(ql2xfwloadbin, int, S_IRUGO|S_IRUSR); +module_param(ql2xfwloadbin, int, S_IRUGO); MODULE_PARM_DESC(ql2xfwloadbin, "Option to specify location from which to load ISP firmware:\n" " 2 -- load firmware via the request_firmware() (hotplug)\n" @@ -135,39 +135,39 @@ MODULE_PARM_DESC(ql2xfwloadbin, " 0 -- use default semantics.\n"); int ql2xetsenable; -module_param(ql2xetsenable, int, S_IRUGO|S_IRUSR); +module_param(ql2xetsenable, int, S_IRUGO); MODULE_PARM_DESC(ql2xetsenable, "Enables firmware ETS burst." "Default is 0 - skip ETS enablement."); int ql2xdbwr = 1; -module_param(ql2xdbwr, int, S_IRUGO|S_IRUSR); +module_param(ql2xdbwr, int, S_IRUGO); MODULE_PARM_DESC(ql2xdbwr, "Option to specify scheme for request queue posting\n" " 0 -- Regular doorbell.\n" " 1 -- CAMRAM doorbell (faster).\n"); int ql2xdontresethba; -module_param(ql2xdontresethba, int, S_IRUGO|S_IRUSR); +module_param(ql2xdontresethba, int, S_IRUGO); MODULE_PARM_DESC(ql2xdontresethba, "Option to specify reset behaviour\n" " 0 (Default) -- Reset on failure.\n" " 1 -- Do not reset on failure.\n"); int ql2xtargetreset = 1; -module_param(ql2xtargetreset, int, S_IRUGO|S_IRUSR); +module_param(ql2xtargetreset, int, S_IRUGO); MODULE_PARM_DESC(ql2xtargetreset, "Enable target reset." "Default is 1 - use hw defaults."); int ql2xgffidenable; -module_param(ql2xgffidenable, int, S_IRUGO|S_IRUSR); +module_param(ql2xgffidenable, int, S_IRUGO); MODULE_PARM_DESC(ql2xgffidenable, "Enables GFF_ID checks of port type. " "Default is 0 - Do not use GFF_ID information."); int ql2xasynctmfenable; -module_param(ql2xasynctmfenable, int, S_IRUGO|S_IRUSR); +module_param(ql2xasynctmfenable, int, S_IRUGO); MODULE_PARM_DESC(ql2xasynctmfenable, "Enables issue of TM IOCBs asynchronously via IOCB mechanism" "Default is 0 - Issue TM IOCBs via mailbox mechanism."); -- cgit v1.2.3-59-g8ed1b From 7a44b86e777fc5d7a267df984d12b05fca59f487 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Tue, 21 Dec 2010 16:00:23 -0800 Subject: [SCSI] qla2xxx: Don't perform a BIG_HAMMER if Get-ID (0x20) mailbox command fails on CNAs. The semantics we employ now in the driver, performing a BIG_HAMMER in the event of Get-ID (0x20) mailbox command failing, should only be done for FC. On FC configurations, it makes sense since advertising is only really performed once, so a BIG_HAMMER to reinitiate the process is needed to restart. Under FCoE, this is not needed, as there's a continous stream of advertisements/ACks at the protocol layer to initiate a relogin/reinitialization process. Signed-off-by: Andrew Vasquez Signed-off-by: Madhuranath Iyengar Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index d0a0dc9d6d36..f948e1a73aec 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -2024,6 +2024,7 @@ qla2x00_configure_hba(scsi_qla_host_t *vha) &loop_id, &al_pa, &area, &domain, &topo, &sw_cap); if (rval != QLA_SUCCESS) { if (LOOP_TRANSITION(vha) || atomic_read(&ha->loop_down_timer) || + IS_QLA8XXX_TYPE(ha) || (rval == QLA_COMMAND_ERROR && loop_id == 0x7)) { DEBUG2(printk("%s(%ld) Loop is in a transition state\n", __func__, vha->host_no)); -- cgit v1.2.3-59-g8ed1b From bc5c2aad17b045ea28ab69e6149c8130ab20731e Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Tue, 21 Dec 2010 16:00:24 -0800 Subject: [SCSI] qla2xxx: Display mailbox register 4 during 8012 AEN for ISP82XX parts. Signed-off-by: Andrew Vasquez Signed-off-by: Madhuranath Iyengar Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_isr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 7f77898486a9..d17ed9a94a0c 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -321,6 +321,7 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) struct qla_hw_data *ha = vha->hw; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24; + struct device_reg_82xx __iomem *reg82 = &ha->iobase->isp82; uint32_t rscn_entry, host_pid; uint8_t rscn_queue_index; unsigned long flags; @@ -498,6 +499,7 @@ skip_rio: case MBA_LOOP_DOWN: /* Loop Down Event */ mbx = IS_QLA81XX(ha) ? RD_REG_WORD(®24->mailbox4) : 0; + mbx = IS_QLA82XX(ha) ? RD_REG_WORD(®82->mailbox_out[4]) : mbx; DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN " "(%x %x %x %x).\n", vha->host_no, mb[1], mb[2], mb[3], mbx)); -- cgit v1.2.3-59-g8ed1b From 0ce87911491d4167198b863c102c7e4d09202561 Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Tue, 21 Dec 2010 16:00:25 -0800 Subject: [SCSI] qla2xxx: Remove code to not reset ISP82xx on failure. Signed-off-by: Giridhar Malavali Signed-off-by: Madhuranath Iyengar Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_gbl.h | 1 - drivers/scsi/qla2xxx/qla_nx.c | 3 +-- drivers/scsi/qla2xxx/qla_os.c | 7 ------- 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 39c4bdda5e3e..89e900adb679 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -95,7 +95,6 @@ extern int ql2xfwloadbin; extern int ql2xetsenable; extern int ql2xshiftctondsd; extern int ql2xdbwr; -extern int ql2xdontresethba; extern int ql2xasynctmfenable; extern int ql2xgffidenable; extern int ql2xenabledif; diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 22b0d781c75a..a971ec31a82e 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -3556,8 +3556,7 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha) qla82xx_idc_lock(ha); break; case QLA82XX_DEV_NEED_RESET: - if (!ql2xdontresethba) - qla82xx_need_reset_handler(vha); + qla82xx_need_reset_handler(vha); break; case QLA82XX_DEV_NEED_QUIESCENT: qla82xx_need_qsnt_handler(vha); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 51e944fafdc6..c194c23ca1fb 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -147,13 +147,6 @@ MODULE_PARM_DESC(ql2xdbwr, " 0 -- Regular doorbell.\n" " 1 -- CAMRAM doorbell (faster).\n"); -int ql2xdontresethba; -module_param(ql2xdontresethba, int, S_IRUGO); -MODULE_PARM_DESC(ql2xdontresethba, - "Option to specify reset behaviour\n" - " 0 (Default) -- Reset on failure.\n" - " 1 -- Do not reset on failure.\n"); - int ql2xtargetreset = 1; module_param(ql2xtargetreset, int, S_IRUGO); MODULE_PARM_DESC(ql2xtargetreset, -- cgit v1.2.3-59-g8ed1b From 900a36e3277ac9109fe364a6a1420c71265f9377 Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Tue, 21 Dec 2010 16:00:26 -0800 Subject: [SCSI] qla2xxx: Fix to avoid recursive lock failure during BSG timeout. Signed-off-by: Giridhar Malavali Signed-off-by: Madhuranath Iyengar Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_bsg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 10942fc9808d..903b0586ded3 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -1512,6 +1512,7 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job) if (((sp_bsg->type == SRB_CT_CMD) || (sp_bsg->type == SRB_ELS_CMD_HST)) && (sp_bsg->u.bsg_job == bsg_job)) { + spin_unlock_irqrestore(&ha->hardware_lock, flags); if (ha->isp_ops->abort_command(sp)) { DEBUG2(qla_printk(KERN_INFO, ha, "scsi(%ld): mbx " @@ -1527,6 +1528,7 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job) bsg_job->req->errors = bsg_job->reply->result = 0; } + spin_lock_irqsave(&ha->hardware_lock, flags); goto done; } } -- cgit v1.2.3-59-g8ed1b From aa5cbf8a70f57c5360ce1bfef692b357c866ae7f Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Tue, 21 Dec 2010 16:00:27 -0800 Subject: [SCSI] qla2xxx: Use sg_next to fetch next sg element while walking sg list. Signed-off-by: Giridhar Malavali Signed-off-by: Madhuranath Iyengar Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_nx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index a971ec31a82e..fdb96a3584a5 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -2561,7 +2561,7 @@ qla2xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); *cur_dsd++ = cpu_to_le32(sg_dma_len(cur_seg)); - cur_seg++; + cur_seg = sg_next(cur_seg); avail_dsds--; } } -- cgit v1.2.3-59-g8ed1b From d4b671c58ebeb56dfc8fe8bcca25e0a06bc9359a Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Sun, 26 Dec 2010 21:46:35 -0800 Subject: [SCSI] bfa: replace bfa_assert with WARN_ON Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa.h | 4 +- drivers/scsi/bfa/bfa_core.c | 12 ++--- drivers/scsi/bfa/bfa_cs.h | 10 ---- drivers/scsi/bfa/bfa_fcpim.c | 42 +++++++-------- drivers/scsi/bfa/bfa_fcs.c | 6 +-- drivers/scsi/bfa/bfa_fcs_fcpim.c | 10 ++-- drivers/scsi/bfa/bfa_fcs_lport.c | 20 +++---- drivers/scsi/bfa/bfa_fcs_rport.c | 4 +- drivers/scsi/bfa/bfa_hw_cb.c | 2 +- drivers/scsi/bfa/bfa_hw_ct.c | 4 +- drivers/scsi/bfa/bfa_ioc.c | 20 +++---- drivers/scsi/bfa/bfa_ioc_ct.c | 4 +- drivers/scsi/bfa/bfa_port.c | 4 +- drivers/scsi/bfa/bfa_svc.c | 110 +++++++++++++++++++-------------------- drivers/scsi/bfa/bfad.c | 2 +- drivers/scsi/bfa/bfad_im.c | 6 +-- 16 files changed, 125 insertions(+), 135 deletions(-) diff --git a/drivers/scsi/bfa/bfa.h b/drivers/scsi/bfa/bfa.h index cabc6b92b25d..56a227b023ae 100644 --- a/drivers/scsi/bfa/bfa.h +++ b/drivers/scsi/bfa/bfa.h @@ -120,8 +120,8 @@ bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg), \ struct list_head *waitq = bfa_reqq(__bfa, __reqq); \ \ - bfa_assert(((__reqq) < BFI_IOC_MAX_CQS)); \ - bfa_assert((__wqe)->qresume && (__wqe)->cbarg); \ + WARN_ON(((__reqq) >= BFI_IOC_MAX_CQS)); \ + WARN_ON(!((__wqe)->qresume && (__wqe)->cbarg)); \ \ list_add_tail(&(__wqe)->qe, waitq); \ } while (0) diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c index 3f7f3742e72c..6e13ba249c83 100644 --- a/drivers/scsi/bfa/bfa_core.c +++ b/drivers/scsi/bfa/bfa_core.c @@ -285,7 +285,7 @@ bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m) bfa_trc(bfa, m->mhdr.msg_class); bfa_trc(bfa, m->mhdr.msg_id); bfa_trc(bfa, m->mhdr.mtag.i2htok); - bfa_assert(0); + WARN_ON(1); bfa_trc_stop(bfa->trcmod); } @@ -433,7 +433,7 @@ bfa_iocfc_send_cfg(void *bfa_arg) struct bfa_iocfc_cfg_s *cfg = &iocfc->cfg; int i; - bfa_assert(cfg->fwcfg.num_cqs <= BFI_IOC_MAX_CQS); + WARN_ON(cfg->fwcfg.num_cqs > BFI_IOC_MAX_CQS); bfa_trc(bfa, cfg->fwcfg.num_cqs); bfa_iocfc_reset_queues(bfa); @@ -753,7 +753,7 @@ bfa_iocfc_disable_cbfn(void *bfa_arg) bfa_cb_queue(bfa, &bfa->iocfc.stop_hcb_qe, bfa_iocfc_stop_cb, bfa); else { - bfa_assert(bfa->iocfc.action == BFA_IOCFC_ACT_DISABLE); + WARN_ON(bfa->iocfc.action != BFA_IOCFC_ACT_DISABLE); bfa_cb_queue(bfa, &bfa->iocfc.dis_hcb_qe, bfa_iocfc_disable_cb, bfa); } @@ -894,7 +894,7 @@ bfa_iocfc_isr(void *bfaarg, struct bfi_mbmsg_s *m) iocfc->updateq_cbfn(iocfc->updateq_cbarg, BFA_STATUS_OK); break; default: - bfa_assert(0); + WARN_ON(1); } } @@ -1063,7 +1063,7 @@ bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo) int i; u32 km_len = 0, dm_len = 0; - bfa_assert((cfg != NULL) && (meminfo != NULL)); + WARN_ON((cfg == NULL) || (meminfo == NULL)); memset((void *)meminfo, 0, sizeof(struct bfa_meminfo_s)); meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_type = @@ -1117,7 +1117,7 @@ bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, bfa->fcs = BFA_FALSE; - bfa_assert((cfg != NULL) && (meminfo != NULL)); + WARN_ON((cfg == NULL) || (meminfo == NULL)); /* * initialize all memory pointers for iterative allocation diff --git a/drivers/scsi/bfa/bfa_cs.h b/drivers/scsi/bfa/bfa_cs.h index 493009d880a8..913057dcb401 100644 --- a/drivers/scsi/bfa/bfa_cs.h +++ b/drivers/scsi/bfa/bfa_cs.h @@ -163,16 +163,6 @@ __bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data) #define bfa_trc_fp(_trcp, _data) #endif -/* - * @ BFA LOG interfaces - */ -#define bfa_assert(__cond) do { \ - if (!(__cond)) { \ - printk(KERN_ERR "assert(%s) failed at %s:%d\\n", \ - #__cond, __FILE__, __LINE__); \ - } \ -} while (0) - #define bfa_sm_fault(__mod, __event) do { \ bfa_trc(__mod, (((u32)0xDEAD << 16) | __event)); \ printk(KERN_ERR "Assertion failure: %s:%d: %d", \ diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c index 5e697f236ef3..f57c066725da 100644 --- a/drivers/scsi/bfa/bfa_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcpim.c @@ -32,12 +32,12 @@ static void bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim); #define bfa_fcpim_additn(__itnim) \ list_add_tail(&(__itnim)->qe, &(__itnim)->fcpim->itnim_q) #define bfa_fcpim_delitn(__itnim) do { \ - bfa_assert(bfa_q_is_on_q(&(__itnim)->fcpim->itnim_q, __itnim)); \ + WARN_ON(!bfa_q_is_on_q(&(__itnim)->fcpim->itnim_q, __itnim)); \ bfa_itnim_update_del_itn_stats(__itnim); \ list_del(&(__itnim)->qe); \ - bfa_assert(list_empty(&(__itnim)->io_q)); \ - bfa_assert(list_empty(&(__itnim)->io_cleanup_q)); \ - bfa_assert(list_empty(&(__itnim)->pending_q)); \ + WARN_ON(!list_empty(&(__itnim)->io_q)); \ + WARN_ON(!list_empty(&(__itnim)->io_cleanup_q)); \ + WARN_ON(!list_empty(&(__itnim)->pending_q)); \ } while (0) #define bfa_itnim_online_cb(__itnim) do { \ @@ -1184,7 +1184,7 @@ bfa_itnim_iotov_start(struct bfa_itnim_s *itnim) if (itnim->fcpim->path_tov > 0) { itnim->iotov_active = BFA_TRUE; - bfa_assert(bfa_itnim_hold_io(itnim)); + WARN_ON(!bfa_itnim_hold_io(itnim)); bfa_timer_start(itnim->bfa, &itnim->timer, bfa_itnim_iotov, itnim, itnim->fcpim->path_tov); } @@ -1262,7 +1262,7 @@ bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m) case BFI_ITNIM_I2H_CREATE_RSP: itnim = BFA_ITNIM_FROM_TAG(fcpim, msg.create_rsp->bfa_handle); - bfa_assert(msg.create_rsp->status == BFA_STATUS_OK); + WARN_ON(msg.create_rsp->status != BFA_STATUS_OK); bfa_stats(itnim, create_comps); bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP); break; @@ -1270,7 +1270,7 @@ bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m) case BFI_ITNIM_I2H_DELETE_RSP: itnim = BFA_ITNIM_FROM_TAG(fcpim, msg.delete_rsp->bfa_handle); - bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK); + WARN_ON(msg.delete_rsp->status != BFA_STATUS_OK); bfa_stats(itnim, delete_comps); bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP); break; @@ -1284,7 +1284,7 @@ bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m) default: bfa_trc(bfa, m->mhdr.msg_id); - bfa_assert(0); + WARN_ON(1); } } @@ -1299,7 +1299,7 @@ bfa_itnim_create(struct bfa_s *bfa, struct bfa_rport_s *rport, void *ditn) struct bfa_itnim_s *itnim; itnim = BFA_ITNIM_FROM_TAG(fcpim, rport->rport_tag); - bfa_assert(itnim->rport == rport); + WARN_ON(itnim->rport != rport); itnim->ditn = ditn; @@ -1416,7 +1416,7 @@ bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) * requests immediately. */ bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); - bfa_assert(bfa_q_is_on_q(&ioim->itnim->pending_q, ioim)); + WARN_ON(!bfa_q_is_on_q(&ioim->itnim->pending_q, ioim)); bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort, ioim); break; @@ -1649,7 +1649,7 @@ bfa_ioim_sm_abort(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) break; case BFA_IOIM_SM_CLEANUP: - bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE); + WARN_ON(ioim->iosp->abort_explicit != BFA_TRUE); ioim->iosp->abort_explicit = BFA_FALSE; if (bfa_ioim_send_abort(ioim)) @@ -1795,7 +1795,7 @@ bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) break; case BFA_IOIM_SM_CLEANUP: - bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE); + WARN_ON(ioim->iosp->abort_explicit != BFA_TRUE); ioim->iosp->abort_explicit = BFA_FALSE; bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull); break; @@ -2236,7 +2236,7 @@ bfa_ioim_sgpg_alloc(struct bfa_ioim_s *ioim) { u16 nsgpgs; - bfa_assert(ioim->nsges > BFI_SGE_INLINE); + WARN_ON(ioim->nsges <= BFI_SGE_INLINE); /* * allocate SG pages needed @@ -2444,7 +2444,7 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m) iotag = be16_to_cpu(rsp->io_tag); ioim = BFA_IOIM_FROM_TAG(fcpim, iotag); - bfa_assert(ioim->iotag == iotag); + WARN_ON(ioim->iotag != iotag); bfa_trc(ioim->bfa, ioim->iotag); bfa_trc(ioim->bfa, rsp->io_status); @@ -2475,13 +2475,13 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m) case BFI_IOIM_STS_PROTO_ERR: bfa_stats(ioim->itnim, iocom_proto_err); - bfa_assert(rsp->reuse_io_tag); + WARN_ON(!rsp->reuse_io_tag); evt = BFA_IOIM_SM_COMP; break; case BFI_IOIM_STS_SQER_NEEDED: bfa_stats(ioim->itnim, iocom_sqer_needed); - bfa_assert(rsp->reuse_io_tag == 0); + WARN_ON(rsp->reuse_io_tag != 0); evt = BFA_IOIM_SM_SQRETRY; break; @@ -2510,7 +2510,7 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m) break; default: - bfa_assert(0); + WARN_ON(1); } bfa_sm_send_event(ioim, evt); @@ -2527,7 +2527,7 @@ bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m) iotag = be16_to_cpu(rsp->io_tag); ioim = BFA_IOIM_FROM_TAG(fcpim, iotag); - bfa_assert(BFA_IOIM_TAG_2_ID(ioim->iotag) == iotag); + WARN_ON(BFA_IOIM_TAG_2_ID(ioim->iotag) != iotag); bfa_trc_fp(ioim->bfa, ioim->iotag); bfa_ioim_cb_profile_comp(fcpim, ioim); @@ -2944,7 +2944,7 @@ bfa_tskim_match_scope(struct bfa_tskim_s *tskim, struct scsi_lun lun) return !memcmp(&tskim->lun, &lun, sizeof(lun)); default: - bfa_assert(0); + WARN_ON(1); } return BFA_FALSE; @@ -3190,7 +3190,7 @@ bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m) u16 tsk_tag = be16_to_cpu(rsp->tsk_tag); tskim = BFA_TSKIM_FROM_TAG(fcpim, tsk_tag); - bfa_assert(tskim->tsk_tag == tsk_tag); + WARN_ON(tskim->tsk_tag != tsk_tag); tskim->tsk_status = rsp->tsk_status; @@ -3225,7 +3225,7 @@ bfa_tskim_alloc(struct bfa_s *bfa, struct bfad_tskim_s *dtsk) void bfa_tskim_free(struct bfa_tskim_s *tskim) { - bfa_assert(bfa_q_is_on_q_func(&tskim->itnim->tsk_q, &tskim->qe)); + WARN_ON(!bfa_q_is_on_q_func(&tskim->itnim->tsk_q, &tskim->qe)); list_del(&tskim->qe); list_add_tail(&tskim->qe, &tskim->fcpim->tskim_free_q); } diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c index e3a41b88a11b..f674f9318629 100644 --- a/drivers/scsi/bfa/bfa_fcs.c +++ b/drivers/scsi/bfa/bfa_fcs.c @@ -920,7 +920,7 @@ bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs) INIT_LIST_HEAD(&fabric->vport_q); INIT_LIST_HEAD(&fabric->vf_q); fabric->lps = bfa_lps_alloc(fcs->bfa); - bfa_assert(fabric->lps); + WARN_ON(!fabric->lps); /* * Initialize fabric delete completion handler. Fabric deletion is @@ -1317,7 +1317,7 @@ bfa_fcs_port_event_handler(void *cbarg, enum bfa_port_linkstate event) break; default: - bfa_assert(0); + WARN_ON(1); } } @@ -1364,7 +1364,7 @@ bfa_fcs_uf_recv(void *cbarg, struct bfa_uf_s *uf) * drop frame if vfid is unknown */ if (!fabric) { - bfa_assert(0); + WARN_ON(1); bfa_stats(fcs, uf.vfid_unknown); bfa_uf_free(uf); return; diff --git a/drivers/scsi/bfa/bfa_fcs_fcpim.c b/drivers/scsi/bfa/bfa_fcs_fcpim.c index 5736ef8c592f..e7b49f4cb51f 100644 --- a/drivers/scsi/bfa/bfa_fcs_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcs_fcpim.c @@ -536,7 +536,7 @@ bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport) if (bfa_itnim == NULL) { bfa_trc(port->fcs, rport->pwwn); bfa_fcb_itnim_free(port->fcs->bfad, itnim_drv); - bfa_assert(0); + WARN_ON(1); return NULL; } @@ -700,7 +700,7 @@ bfa_fcs_itnim_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn) if (!rport) return NULL; - bfa_assert(rport->itnim != NULL); + WARN_ON(rport->itnim == NULL); return rport->itnim; } @@ -729,7 +729,7 @@ bfa_fcs_itnim_stats_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn, { struct bfa_fcs_itnim_s *itnim = NULL; - bfa_assert(port != NULL); + WARN_ON(port == NULL); itnim = bfa_fcs_itnim_lookup(port, rpwwn); @@ -746,7 +746,7 @@ bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s *port, wwn_t rpwwn) { struct bfa_fcs_itnim_s *itnim = NULL; - bfa_assert(port != NULL); + WARN_ON(port == NULL); itnim = bfa_fcs_itnim_lookup(port, rpwwn); @@ -778,6 +778,6 @@ bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim, break; default: - bfa_assert(0); + WARN_ON(1); } } diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c index eb804980cde9..4e2eb92ba028 100644 --- a/drivers/scsi/bfa/bfa_fcs_lport.c +++ b/drivers/scsi/bfa/bfa_fcs_lport.c @@ -351,7 +351,7 @@ bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port, * This is a different device with the same pid. Old device * disappeared. Send implicit LOGO to old device. */ - bfa_assert(rport->pwwn != plogi->port_name); + WARN_ON(rport->pwwn == plogi->port_name); bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP); /* @@ -364,7 +364,7 @@ bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port, /* * PLOGI crossing each other. */ - bfa_assert(rport->pwwn == WWN_NULL); + WARN_ON(rport->pwwn != WWN_NULL); bfa_fcs_rport_plogi(rport, rx_fchs, plogi); } @@ -532,19 +532,19 @@ bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port) static void bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port) { - bfa_assert(0); + WARN_ON(1); } static void bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port) { - bfa_assert(0); + WARN_ON(1); } static void bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port) { - bfa_assert(0); + WARN_ON(1); } static void @@ -777,7 +777,7 @@ bfa_fcs_lport_del_rport( struct bfa_fcs_lport_s *port, struct bfa_fcs_rport_s *rport) { - bfa_assert(bfa_q_is_on_q(&port->rport_q, rport)); + WARN_ON(!bfa_q_is_on_q(&port->rport_q, rport)); list_del(&rport->qe); port->num_rports--; @@ -1005,7 +1005,7 @@ bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port) */ if (port->num_rports > 0) { rport = bfa_fcs_lport_get_rport_by_pid(port, 0); - bfa_assert(rport != NULL); + WARN_ON(rport == NULL); if (rport) { bfa_trc(port->fcs, rport->pwwn); bfa_sm_send_event(rport, RPSM_EVENT_DELETE); @@ -4153,7 +4153,7 @@ bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port) for (ii = 0 ; ii < nwwns; ++ii) { rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]); - bfa_assert(rport); + WARN_ON(!rport); } } @@ -4616,7 +4616,7 @@ bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port, default: - bfa_assert(0); + WARN_ON(1); nsquery = BFA_TRUE; } } @@ -4797,7 +4797,7 @@ bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn) struct bfa_fcs_vport_s *vport; bfa_fcs_vf_t *vf; - bfa_assert(fcs != NULL); + WARN_ON(fcs == NULL); vf = bfa_fcs_vf_lookup(fcs, vf_id); if (vf == NULL) { diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c index 711f2d992a97..caaee6f06937 100644 --- a/drivers/scsi/bfa/bfa_fcs_rport.c +++ b/drivers/scsi/bfa/bfa_fcs_rport.c @@ -1968,7 +1968,7 @@ bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid) /* * allocate FC-4s */ - bfa_assert(bfa_fcs_lport_is_initiator(port)); + WARN_ON(!bfa_fcs_lport_is_initiator(port)); if (bfa_fcs_lport_is_initiator(port)) { rport->itnim = bfa_fcs_itnim_create(rport); @@ -2897,7 +2897,7 @@ bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg, num_ents = be16_to_cpu(rpsc2_acc->num_pids); bfa_trc(rport->fcs, num_ents); if (num_ents > 0) { - bfa_assert(rpsc2_acc->port_info[0].pid != rport->pid); + WARN_ON(rpsc2_acc->port_info[0].pid == rport->pid); bfa_trc(rport->fcs, be16_to_cpu(rpsc2_acc->port_info[0].pid)); bfa_trc(rport->fcs, diff --git a/drivers/scsi/bfa/bfa_hw_cb.c b/drivers/scsi/bfa/bfa_hw_cb.c index 1fa15edabcdd..977e681ec803 100644 --- a/drivers/scsi/bfa/bfa_hw_cb.c +++ b/drivers/scsi/bfa/bfa_hw_cb.c @@ -111,7 +111,7 @@ bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs) { int i; - bfa_assert((nvecs == 1) || (nvecs == __HFN_NUMINTS)); + WARN_ON((nvecs != 1) && (nvecs != __HFN_NUMINTS)); bfa->msix.nvecs = nvecs; if (nvecs == 1) { diff --git a/drivers/scsi/bfa/bfa_hw_ct.c b/drivers/scsi/bfa/bfa_hw_ct.c index 68077c4c4d55..21018d98a07b 100644 --- a/drivers/scsi/bfa/bfa_hw_ct.c +++ b/drivers/scsi/bfa/bfa_hw_ct.c @@ -117,7 +117,7 @@ bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap, void bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs) { - bfa_assert((nvecs == 1) || (nvecs == BFA_MSIX_CT_MAX)); + WARN_ON((nvecs != 1) && (nvecs != BFA_MSIX_CT_MAX)); bfa_trc(bfa, nvecs); bfa->msix.nvecs = nvecs; @@ -144,7 +144,7 @@ bfa_hwct_msix_install(struct bfa_s *bfa) for (; i <= BFA_MSIX_RME_Q3; i++) bfa->msix.handler[i] = bfa_msix_rspq; - bfa_assert(i == BFA_MSIX_LPU_ERR); + WARN_ON(i != BFA_MSIX_LPU_ERR); bfa->msix.handler[BFA_MSIX_LPU_ERR] = bfa_msix_lpu_err; } diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index 05b0ff93284a..431cf72f7426 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -1219,7 +1219,7 @@ bfa_ioc_sem_get(void __iomem *sem_reg) if (r32 == 0) return BFA_TRUE; - bfa_assert(cnt < BFA_SEM_SPINCNT); + WARN_ON(cnt >= BFA_SEM_SPINCNT); return BFA_FALSE; } @@ -1274,7 +1274,7 @@ bfa_ioc_lmem_init(struct bfa_ioc_s *ioc) * If memory initialization is not successful, IOC timeout will catch * such failures. */ - bfa_assert(pss_ctl & __PSS_LMEM_INIT_DONE); + WARN_ON(!(pss_ctl & __PSS_LMEM_INIT_DONE)); bfa_trc(ioc, pss_ctl); pss_ctl &= ~(__PSS_LMEM_INIT_DONE | __PSS_LMEM_INIT_EN); @@ -1503,7 +1503,7 @@ bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len) bfa_trc(ioc, msgp[0]); bfa_trc(ioc, len); - bfa_assert(len <= BFI_IOC_MSGLEN_MAX); + WARN_ON(len > BFI_IOC_MSGLEN_MAX); /* * first write msg to mailbox registers @@ -2010,7 +2010,7 @@ bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m) default: bfa_trc(ioc, msg->mh.msg_id); - bfa_assert(0); + WARN_ON(1); } } @@ -2345,7 +2345,7 @@ bfa_ioc_get_type(struct bfa_ioc_s *ioc) else if (ioc->ioc_mc == BFI_MC_LL) return BFA_IOC_TYPE_LL; else { - bfa_assert(ioc->ioc_mc == BFI_MC_LL); + WARN_ON(ioc->ioc_mc != BFI_MC_LL); return BFA_IOC_TYPE_LL; } } @@ -2369,7 +2369,7 @@ bfa_ioc_get_adapter_fw_ver(struct bfa_ioc_s *ioc, char *fw_ver) void bfa_ioc_get_pci_chip_rev(struct bfa_ioc_s *ioc, char *chip_rev) { - bfa_assert(chip_rev); + WARN_ON(!chip_rev); memset((void *)chip_rev, 0, BFA_IOC_CHIP_REV_LEN); @@ -2401,7 +2401,7 @@ bfa_ioc_get_adapter_model(struct bfa_ioc_s *ioc, char *model) { struct bfi_ioc_attr_s *ioc_attr; - bfa_assert(model); + WARN_ON(!model); memset((void *)model, 0, BFA_ADAPTER_MODEL_NAME_LEN); ioc_attr = ioc->attr; @@ -2772,8 +2772,8 @@ bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer, void (*timercb) (void *), void *arg, unsigned int timeout) { - bfa_assert(timercb != NULL); - bfa_assert(!bfa_q_is_on_q(&mod->timer_q, timer)); + WARN_ON(timercb == NULL); + WARN_ON(bfa_q_is_on_q(&mod->timer_q, timer)); timer->timeout = timeout; timer->timercb = timercb; @@ -2788,7 +2788,7 @@ bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer, void bfa_timer_stop(struct bfa_timer_s *timer) { - bfa_assert(!list_empty(&timer->qe)); + WARN_ON(list_empty(&timer->qe)); list_del(&timer->qe); } diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c index 9da55a836bfb..ccfecfca0745 100644 --- a/drivers/scsi/bfa/bfa_ioc_ct.c +++ b/drivers/scsi/bfa/bfa_ioc_ct.c @@ -113,7 +113,7 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc) /* * Use count cannot be non-zero and chip in uninitialized state. */ - bfa_assert(ioc_fwstate != BFI_IOC_UNINIT); + WARN_ON(ioc_fwstate == BFI_IOC_UNINIT); /* * Check if another driver with a different firmware is active @@ -158,7 +158,7 @@ bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc) */ bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); usecnt = readl(ioc->ioc_regs.ioc_usage_reg); - bfa_assert(usecnt > 0); + WARN_ON(usecnt <= 0); usecnt--; writel(usecnt, ioc->ioc_regs.ioc_usage_reg); diff --git a/drivers/scsi/bfa/bfa_port.c b/drivers/scsi/bfa/bfa_port.c index 45b3486cca9c..3f8e9d6066ec 100644 --- a/drivers/scsi/bfa/bfa_port.c +++ b/drivers/scsi/bfa/bfa_port.c @@ -186,7 +186,7 @@ bfa_port_isr(void *cbarg, struct bfi_mbmsg_s *m) break; default: - bfa_assert(0); + WARN_ON(1); } } @@ -435,7 +435,7 @@ bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc, { struct timeval tv; - bfa_assert(port); + WARN_ON(!port); port->dev = dev; port->ioc = ioc; diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c index b7df5534da85..d33e93a7a672 100644 --- a/drivers/scsi/bfa/bfa_svc.c +++ b/drivers/scsi/bfa/bfa_svc.c @@ -309,7 +309,7 @@ bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec) return; if (plkd_validate_logrec(pl_rec)) { - bfa_assert(0); + WARN_ON(1); return; } @@ -601,15 +601,15 @@ bfa_fcxp_init_reqrsp(struct bfa_fcxp_s *fcxp, bfa_fcxp_get_sglen_t sglen_cbfn) { - bfa_assert(bfa != NULL); + WARN_ON(bfa == NULL); bfa_trc(bfa, fcxp->fcxp_tag); if (n_sgles == 0) { *use_ibuf = 1; } else { - bfa_assert(*sga_cbfn != NULL); - bfa_assert(*sglen_cbfn != NULL); + WARN_ON(*sga_cbfn == NULL); + WARN_ON(*sglen_cbfn == NULL); *use_ibuf = 0; *r_sga_cbfn = sga_cbfn; @@ -621,7 +621,7 @@ bfa_fcxp_init_reqrsp(struct bfa_fcxp_s *fcxp, * alloc required sgpgs */ if (n_sgles > BFI_SGE_INLINE) - bfa_assert(0); + WARN_ON(1); } } @@ -635,7 +635,7 @@ bfa_fcxp_init(struct bfa_fcxp_s *fcxp, bfa_fcxp_get_sglen_t rsp_sglen_cbfn) { - bfa_assert(bfa != NULL); + WARN_ON(bfa == NULL); bfa_trc(bfa, fcxp->fcxp_tag); @@ -672,7 +672,7 @@ bfa_fcxp_put(struct bfa_fcxp_s *fcxp) return; } - bfa_assert(bfa_q_is_on_q(&mod->fcxp_active_q, fcxp)); + WARN_ON(!bfa_q_is_on_q(&mod->fcxp_active_q, fcxp)); list_del(&fcxp->qe); list_add_tail(&fcxp->qe, &mod->fcxp_free_q); } @@ -721,7 +721,7 @@ hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp) fcxp = BFA_FCXP_FROM_TAG(mod, fcxp_tag); - bfa_assert(fcxp->send_cbfn != NULL); + WARN_ON(fcxp->send_cbfn == NULL); hal_fcxp_rx_plog(mod->bfa, fcxp, fcxp_rsp); @@ -877,13 +877,13 @@ bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req) BFA_FCXP_REQ_PLD_PA(fcxp)); } else { if (fcxp->nreq_sgles > 0) { - bfa_assert(fcxp->nreq_sgles == 1); + WARN_ON(fcxp->nreq_sgles != 1); hal_fcxp_set_local_sges(send_req->req_sge, reqi->req_tot_len, fcxp->req_sga_cbfn(fcxp->caller, 0)); } else { - bfa_assert(reqi->req_tot_len == 0); + WARN_ON(reqi->req_tot_len != 0); hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0); } } @@ -892,20 +892,20 @@ bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req) * setup rsp sgles */ if (fcxp->use_irspbuf == 1) { - bfa_assert(rspi->rsp_maxlen <= BFA_FCXP_MAX_LBUF_SZ); + WARN_ON(rspi->rsp_maxlen > BFA_FCXP_MAX_LBUF_SZ); hal_fcxp_set_local_sges(send_req->rsp_sge, rspi->rsp_maxlen, BFA_FCXP_RSP_PLD_PA(fcxp)); } else { if (fcxp->nrsp_sgles > 0) { - bfa_assert(fcxp->nrsp_sgles == 1); + WARN_ON(fcxp->nrsp_sgles != 1); hal_fcxp_set_local_sges(send_req->rsp_sge, rspi->rsp_maxlen, fcxp->rsp_sga_cbfn(fcxp->caller, 0)); } else { - bfa_assert(rspi->rsp_maxlen == 0); + WARN_ON(rspi->rsp_maxlen != 0); hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0); } } @@ -950,7 +950,7 @@ bfa_fcxp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles, { struct bfa_fcxp_s *fcxp = NULL; - bfa_assert(bfa != NULL); + WARN_ON(bfa == NULL); fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa)); if (fcxp == NULL) @@ -977,7 +977,7 @@ bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp) struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod; void *reqbuf; - bfa_assert(fcxp->use_ireqbuf == 1); + WARN_ON(fcxp->use_ireqbuf != 1); reqbuf = ((u8 *)mod->req_pld_list_kva) + fcxp->fcxp_tag * mod->req_pld_sz; return reqbuf; @@ -1004,7 +1004,7 @@ bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp) struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod; void *rspbuf; - bfa_assert(fcxp->use_irspbuf == 1); + WARN_ON(fcxp->use_irspbuf != 1); rspbuf = ((u8 *)mod->rsp_pld_list_kva) + fcxp->fcxp_tag * mod->rsp_pld_sz; @@ -1023,7 +1023,7 @@ bfa_fcxp_free(struct bfa_fcxp_s *fcxp) { struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod; - bfa_assert(fcxp != NULL); + WARN_ON(fcxp == NULL); bfa_trc(mod->bfa, fcxp->fcxp_tag); bfa_fcxp_put(fcxp); } @@ -1102,7 +1102,7 @@ bfa_status_t bfa_fcxp_abort(struct bfa_fcxp_s *fcxp) { bfa_trc(fcxp->fcxp_mod->bfa, fcxp->fcxp_tag); - bfa_assert(0); + WARN_ON(1); return BFA_STATUS_OK; } @@ -1117,7 +1117,7 @@ bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe, { struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa); - bfa_assert(list_empty(&mod->fcxp_free_q)); + WARN_ON(!list_empty(&mod->fcxp_free_q)); wqe->alloc_cbfn = alloc_cbfn; wqe->alloc_cbarg = alloc_cbarg; @@ -1138,7 +1138,7 @@ bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe) { struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa); - bfa_assert(bfa_q_is_on_q(&mod->wait_q, wqe)); + WARN_ON(!bfa_q_is_on_q(&mod->wait_q, wqe)); list_del(&wqe->qe); } @@ -1169,7 +1169,7 @@ bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg) default: bfa_trc(bfa, msg->mhdr.msg_id); - bfa_assert(0); + WARN_ON(1); } } @@ -1555,7 +1555,7 @@ bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp) struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa); struct bfa_lps_s *lps; - bfa_assert(rsp->lp_tag < mod->num_lps); + WARN_ON(rsp->lp_tag >= mod->num_lps); lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag); lps->status = rsp->status; @@ -1603,7 +1603,7 @@ bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp) struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa); struct bfa_lps_s *lps; - bfa_assert(rsp->lp_tag < mod->num_lps); + WARN_ON(rsp->lp_tag >= mod->num_lps); lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag); bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP); @@ -1656,7 +1656,7 @@ bfa_lps_send_login(struct bfa_lps_s *lps) struct bfi_lps_login_req_s *m; m = bfa_reqq_next(lps->bfa, lps->reqq); - bfa_assert(m); + WARN_ON(!m); bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ, bfa_lpuid(lps->bfa)); @@ -1681,7 +1681,7 @@ bfa_lps_send_logout(struct bfa_lps_s *lps) struct bfi_lps_logout_req_s *m; m = bfa_reqq_next(lps->bfa, lps->reqq); - bfa_assert(m); + WARN_ON(!m); bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ, bfa_lpuid(lps->bfa)); @@ -1700,7 +1700,7 @@ bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps) struct bfi_lps_n2n_pid_req_s *m; m = bfa_reqq_next(lps->bfa, lps->reqq); - bfa_assert(m); + WARN_ON(!m); bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_N2N_PID_REQ, bfa_lpuid(lps->bfa)); @@ -1969,7 +1969,7 @@ bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m) default: bfa_trc(bfa, m->mhdr.msg_id); - bfa_assert(0); + WARN_ON(1); } } @@ -2099,7 +2099,7 @@ bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport, bfa_fcport_update_linkinfo(fcport); bfa_sm_set_state(fcport, bfa_fcport_sm_linkup); - bfa_assert(fcport->event_cbfn); + WARN_ON(!fcport->event_cbfn); bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE); break; @@ -2150,7 +2150,7 @@ bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport, case BFA_FCPORT_SM_LINKUP: bfa_fcport_update_linkinfo(fcport); bfa_sm_set_state(fcport, bfa_fcport_sm_linkup); - bfa_assert(fcport->event_cbfn); + WARN_ON(!fcport->event_cbfn); bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkup"); if (!bfa_ioc_get_fcmode(&fcport->bfa->ioc)) { @@ -2754,7 +2754,7 @@ bfa_fcport_scn(struct bfa_fcport_s *fcport, enum bfa_port_linkstate event, bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKDOWN); break; default: - bfa_assert(0); + WARN_ON(1); } } @@ -3219,8 +3219,8 @@ bfa_trunk_scn(struct bfa_fcport_s *fcport, struct bfi_fcport_trunk_scn_s *scn) int link_bm = 0; bfa_trc(fcport->bfa, fcport->cfg.trunked); - bfa_assert(scn->trunk_state == BFA_TRUNK_ONLINE || - scn->trunk_state == BFA_TRUNK_OFFLINE); + WARN_ON(scn->trunk_state != BFA_TRUNK_ONLINE && + scn->trunk_state != BFA_TRUNK_OFFLINE); bfa_trc(fcport->bfa, trunk->attr.state); bfa_trc(fcport->bfa, scn->trunk_state); @@ -3329,9 +3329,9 @@ bfa_fcport_init(struct bfa_s *bfa) fcport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc); fcport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc); - bfa_assert(fcport->cfg.maxfrsize); - bfa_assert(fcport->cfg.rx_bbcredit); - bfa_assert(fcport->speed_sup); + WARN_ON(!fcport->cfg.maxfrsize); + WARN_ON(!fcport->cfg.rx_bbcredit); + WARN_ON(!fcport->speed_sup); } /* @@ -3428,7 +3428,7 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg) break; default: - bfa_assert(0); + WARN_ON(1); break; } } @@ -4310,8 +4310,8 @@ bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, mod->rps_list = rp; mod->num_rports = cfg->fwcfg.num_rports; - bfa_assert(mod->num_rports && - !(mod->num_rports & (mod->num_rports - 1))); + WARN_ON(!mod->num_rports || + (mod->num_rports & (mod->num_rports - 1))); for (i = 0; i < mod->num_rports; i++, rp++) { memset(rp, 0, sizeof(struct bfa_rport_s)); @@ -4379,7 +4379,7 @@ bfa_rport_free(struct bfa_rport_s *rport) { struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(rport->bfa); - bfa_assert(bfa_q_is_on_q(&mod->rp_active_q, rport)); + WARN_ON(!bfa_q_is_on_q(&mod->rp_active_q, rport)); list_del(&rport->qe); list_add_tail(&rport->qe, &mod->rp_free_q); } @@ -4492,13 +4492,13 @@ bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m) rp = BFA_RPORT_FROM_TAG(bfa, msg.create_rsp->bfa_handle); rp->fw_handle = msg.create_rsp->fw_handle; rp->qos_attr = msg.create_rsp->qos_attr; - bfa_assert(msg.create_rsp->status == BFA_STATUS_OK); + WARN_ON(msg.create_rsp->status != BFA_STATUS_OK); bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP); break; case BFI_RPORT_I2H_DELETE_RSP: rp = BFA_RPORT_FROM_TAG(bfa, msg.delete_rsp->bfa_handle); - bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK); + WARN_ON(msg.delete_rsp->status != BFA_STATUS_OK); bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP); break; @@ -4510,7 +4510,7 @@ bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m) default: bfa_trc(bfa, m->mhdr.msg_id); - bfa_assert(0); + WARN_ON(1); } } @@ -4534,7 +4534,7 @@ bfa_rport_create(struct bfa_s *bfa, void *rport_drv) rp->rport_drv = rport_drv; memset(&rp->stats, 0, sizeof(rp->stats)); - bfa_assert(bfa_sm_cmp_state(rp, bfa_rport_sm_uninit)); + WARN_ON(!bfa_sm_cmp_state(rp, bfa_rport_sm_uninit)); bfa_sm_send_event(rp, BFA_RPORT_SM_CREATE); return rp; @@ -4543,7 +4543,7 @@ bfa_rport_create(struct bfa_s *bfa, void *rport_drv) void bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info) { - bfa_assert(rport_info->max_frmsz != 0); + WARN_ON(rport_info->max_frmsz == 0); /* * Some JBODs are seen to be not setting PDU size correctly in PLOGI @@ -4561,8 +4561,8 @@ bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info) void bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed) { - bfa_assert(speed != 0); - bfa_assert(speed != BFA_PORT_SPEED_AUTO); + WARN_ON(speed == 0); + WARN_ON(speed == BFA_PORT_SPEED_AUTO); rport->rport_info.speed = speed; bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED); @@ -4622,7 +4622,7 @@ bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, sgpg_pa.pa = mod->sgpg_arr_pa; mod->free_sgpgs = mod->num_sgpgs; - bfa_assert(!(sgpg_pa.pa & (sizeof(struct bfi_sgpg_s) - 1))); + WARN_ON(sgpg_pa.pa & (sizeof(struct bfi_sgpg_s) - 1)); for (i = 0; i < mod->num_sgpgs; i++) { memset(hsgpg, 0, sizeof(*hsgpg)); @@ -4677,7 +4677,7 @@ bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs) for (i = 0; i < nsgpgs; i++) { bfa_q_deq(&mod->sgpg_q, &hsgpg); - bfa_assert(hsgpg); + WARN_ON(!hsgpg); list_add_tail(&hsgpg->qe, sgpg_q); } @@ -4694,7 +4694,7 @@ bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpg) bfa_trc_fp(bfa, nsgpg); mod->free_sgpgs += nsgpg; - bfa_assert(mod->free_sgpgs <= mod->num_sgpgs); + WARN_ON(mod->free_sgpgs > mod->num_sgpgs); list_splice_tail_init(sgpg_q, &mod->sgpg_q); @@ -4724,8 +4724,8 @@ bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg) { struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa); - bfa_assert(nsgpg > 0); - bfa_assert(nsgpg > mod->free_sgpgs); + WARN_ON(nsgpg <= 0); + WARN_ON(nsgpg <= mod->free_sgpgs); wqe->nsgpg_total = wqe->nsgpg = nsgpg; @@ -4736,7 +4736,7 @@ bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg) /* * no one else is waiting for SGPG */ - bfa_assert(list_empty(&mod->sgpg_wait_q)); + WARN_ON(!list_empty(&mod->sgpg_wait_q)); list_splice_tail_init(&mod->sgpg_q, &wqe->sgpg_q); wqe->nsgpg -= mod->free_sgpgs; mod->free_sgpgs = 0; @@ -4750,7 +4750,7 @@ bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe) { struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa); - bfa_assert(bfa_q_is_on_q(&mod->sgpg_wait_q, wqe)); + WARN_ON(!bfa_q_is_on_q(&mod->sgpg_wait_q, wqe)); list_del(&wqe->qe); if (wqe->nsgpg_total != wqe->nsgpg) @@ -4982,7 +4982,7 @@ uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m) uf->data_ptr = buf; uf->data_len = m->xfr_len; - bfa_assert(uf->data_len >= sizeof(struct fchs_s)); + WARN_ON(uf->data_len < sizeof(struct fchs_s)); if (uf->data_len == sizeof(struct fchs_s)) { bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_UF, BFA_PL_EID_RX, @@ -5072,7 +5072,7 @@ bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg) default: bfa_trc(bfa, msg->mhdr.msg_id); - bfa_assert(0); + WARN_ON(1); } } diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index c80540e576cd..4e94d28ae328 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -532,7 +532,7 @@ bfad_hal_mem_release(struct bfad_s *bfad) (dma_addr_t) meminfo_elem->dma); break; default: - bfa_assert(0); + WARN_ON(1); break; } } diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index 53cea3d33351..f0bcda8f077f 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c @@ -449,7 +449,7 @@ bfa_fcb_itnim_free(struct bfad_s *bfad, struct bfad_itnim_s *itnim_drv) struct bfad_im_s *im = itnim_drv->im; /* online to free state transtion should not happen */ - bfa_assert(itnim_drv->state != ITNIM_STATE_ONLINE); + WARN_ON(itnim_drv->state == ITNIM_STATE_ONLINE); itnim_drv->queue_work = 1; /* offline request is not yet done, use the same request to free */ @@ -664,7 +664,7 @@ bfad_im_port_clean(struct bfad_im_port_s *im_port) } /* the itnim_mapped_list must be empty at this time */ - bfa_assert(list_empty(&im_port->itnim_mapped_list)); + WARN_ON(!list_empty(&im_port->itnim_mapped_list)); spin_unlock_irqrestore(&bfad->bfad_lock, flags); } @@ -1111,7 +1111,7 @@ bfad_im_itnim_work_handler(struct work_struct *work) kfree(itnim); break; default: - bfa_assert(0); + WARN_ON(1); break; } -- cgit v1.2.3-59-g8ed1b From 2f2f40a45845e52fbbe07bcd3e09ccff44feb01b Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Sun, 26 Dec 2010 21:48:53 -0800 Subject: [SCSI] bfa: remove inactive functions This patch removes some inactive functions and macros. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/Makefile | 2 -- drivers/scsi/bfa/bfa_core.c | 8 -------- drivers/scsi/bfa/bfa_cs.h | 35 ----------------------------------- drivers/scsi/bfa/bfa_fcpim.c | 23 ----------------------- drivers/scsi/bfa/bfa_svc.c | 4 ---- drivers/scsi/bfa/bfad.c | 1 - drivers/scsi/bfa/bfad_im.c | 1 - 7 files changed, 74 deletions(-) diff --git a/drivers/scsi/bfa/Makefile b/drivers/scsi/bfa/Makefile index ed26a6a97a44..4ce6f4942327 100644 --- a/drivers/scsi/bfa/Makefile +++ b/drivers/scsi/bfa/Makefile @@ -4,5 +4,3 @@ bfa-y := bfad.o bfad_im.o bfad_attr.o bfad_debugfs.o bfa-y += bfa_ioc.o bfa_ioc_cb.o bfa_ioc_ct.o bfa_hw_cb.o bfa_hw_ct.o bfa-y += bfa_fcs.o bfa_fcs_lport.o bfa_fcs_rport.o bfa_fcs_fcpim.o bfa_fcbuild.o bfa-y += bfa_port.o bfa_fcpim.o bfa_core.o bfa_svc.o - -ccflags-y := -DBFA_PERF_BUILD diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c index 6e13ba249c83..d6c7e05ae4ce 100644 --- a/drivers/scsi/bfa/bfa_core.c +++ b/drivers/scsi/bfa/bfa_core.c @@ -296,8 +296,6 @@ bfa_msix_rspq(struct bfa_s *bfa, int qid) u32 pi, ci; struct list_head *waitq; - bfa_trc_fp(bfa, qid); - qid &= (BFI_IOC_MAX_CQS - 1); bfa->iocfc.hwif.hw_rspq_ack(bfa, qid); @@ -305,16 +303,10 @@ bfa_msix_rspq(struct bfa_s *bfa, int qid) ci = bfa_rspq_ci(bfa, qid); pi = bfa_rspq_pi(bfa, qid); - bfa_trc_fp(bfa, ci); - bfa_trc_fp(bfa, pi); - if (bfa->rme_process) { while (ci != pi) { m = bfa_rspq_elem(bfa, qid, ci); - bfa_assert_fp(m->mhdr.msg_class < BFI_MC_MAX); - bfa_isrs[m->mhdr.msg_class] (bfa, m); - CQ_INCR(ci, bfa->iocfc.cfg.drvcfg.num_rspq_elems); } } diff --git a/drivers/scsi/bfa/bfa_cs.h b/drivers/scsi/bfa/bfa_cs.h index 913057dcb401..12bfeed268eb 100644 --- a/drivers/scsi/bfa/bfa_cs.h +++ b/drivers/scsi/bfa/bfa_cs.h @@ -107,13 +107,6 @@ bfa_trc_stop(struct bfa_trc_mod_s *trcm) trcm->stopped = 1; } -#ifdef FWTRC -extern void dc_flush(void *data); -#else -#define dc_flush(data) -#endif - - static inline void __bfa_trc(struct bfa_trc_mod_s *trcm, int fileno, int line, u64 data) { @@ -127,12 +120,10 @@ __bfa_trc(struct bfa_trc_mod_s *trcm, int fileno, int line, u64 data) trc->line = (u16) line; trc->data.u64 = data; trc->timestamp = BFA_TRC_TS(trcm); - dc_flush(trc); trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1); if (trcm->tail == trcm->head) trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1); - dc_flush(trcm); } @@ -149,32 +140,18 @@ __bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data) trc->line = (u16) line; trc->data.u32.u32 = data; trc->timestamp = BFA_TRC_TS(trcm); - dc_flush(trc); trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1); if (trcm->tail == trcm->head) trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1); - dc_flush(trcm); } -#ifndef BFA_PERF_BUILD -#define bfa_trc_fp(_trcp, _data) bfa_trc(_trcp, _data) -#else -#define bfa_trc_fp(_trcp, _data) -#endif - #define bfa_sm_fault(__mod, __event) do { \ bfa_trc(__mod, (((u32)0xDEAD << 16) | __event)); \ printk(KERN_ERR "Assertion failure: %s:%d: %d", \ __FILE__, __LINE__, (__event)); \ } while (0) -#ifndef BFA_PERF_BUILD -#define bfa_assert_fp(__cond) bfa_assert(__cond) -#else -#define bfa_assert_fp(__cond) -#endif - /* BFA queue definitions */ #define bfa_q_first(_q) ((void *)(((struct list_head *) (_q))->next)) #define bfa_q_next(_qe) (((struct list_head *) (_qe))->next) @@ -197,7 +174,6 @@ __bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data) bfa_q_prev(bfa_q_next(*((struct list_head **) _qe))) = \ (struct list_head *) (_q); \ bfa_q_next(_q) = bfa_q_next(*((struct list_head **) _qe));\ - BFA_Q_DBG_INIT(*((struct list_head **) _qe)); \ } else { \ *((struct list_head **) (_qe)) = (struct list_head *) NULL;\ } \ @@ -212,7 +188,6 @@ __bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data) bfa_q_next(bfa_q_prev(*((struct list_head **) _qe))) = \ (struct list_head *) (_q); \ bfa_q_prev(_q) = bfa_q_prev(*(struct list_head **) _qe);\ - BFA_Q_DBG_INIT(*((struct list_head **) _qe)); \ } else { \ *((struct list_head **) (_qe)) = (struct list_head *) NULL;\ } \ @@ -234,16 +209,6 @@ bfa_q_is_on_q_func(struct list_head *q, struct list_head *qe) return 0; } -/* - * #ifdef BFA_DEBUG (Using bfa_assert to check for debug_build is not - * consistent across modules) - */ -#ifndef BFA_PERF_BUILD -#define BFA_Q_DBG_INIT(_qe) bfa_q_qe_init(_qe) -#else -#define BFA_Q_DBG_INIT(_qe) -#endif - #define bfa_q_is_on_q(_q, _qe) \ bfa_q_is_on_q_func(_q, (struct list_head *)(_qe)) diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c index f57c066725da..a4989a02e494 100644 --- a/drivers/scsi/bfa/bfa_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcpim.c @@ -1367,9 +1367,6 @@ bfa_itnim_clear_stats(struct bfa_itnim_s *itnim) static void bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) { - bfa_trc_fp(ioim->bfa, ioim->iotag); - bfa_trc_fp(ioim->bfa, event); - switch (event) { case BFA_IOIM_SM_START: if (!bfa_itnim_is_online(ioim->itnim)) { @@ -1479,9 +1476,6 @@ bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) static void bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) { - bfa_trc_fp(ioim->bfa, ioim->iotag); - bfa_trc_fp(ioim->bfa, event); - switch (event) { case BFA_IOIM_SM_COMP_GOOD: bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); @@ -1563,9 +1557,6 @@ bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) static void bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) { - bfa_trc_fp(ioim->bfa, ioim->iotag); - bfa_trc_fp(ioim->bfa, event); - switch (event) { case BFA_IOIM_SM_FREE: /* abts and rrq done. Now retry the IO with new tag */ @@ -1886,9 +1877,6 @@ bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) static void bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) { - bfa_trc_fp(ioim->bfa, ioim->iotag); - bfa_trc_fp(ioim->bfa, event); - switch (event) { case BFA_IOIM_SM_HCB: bfa_sm_set_state(ioim, bfa_ioim_sm_uninit); @@ -2529,9 +2517,7 @@ bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m) ioim = BFA_IOIM_FROM_TAG(fcpim, iotag); WARN_ON(BFA_IOIM_TAG_2_ID(ioim->iotag) != iotag); - bfa_trc_fp(ioim->bfa, ioim->iotag); bfa_ioim_cb_profile_comp(fcpim, ioim); - bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD); } @@ -2608,7 +2594,6 @@ bfa_ioim_alloc(struct bfa_s *bfa, struct bfad_ioim_s *dio, fcpim->ios_active++; list_add_tail(&ioim->qe, &itnim->io_q); - bfa_trc_fp(ioim->bfa, ioim->iotag); return ioim; } @@ -2618,12 +2603,6 @@ bfa_ioim_free(struct bfa_ioim_s *ioim) { struct bfa_fcpim_mod_s *fcpim = ioim->fcpim; - bfa_trc_fp(ioim->bfa, ioim->iotag); - bfa_assert_fp(bfa_sm_cmp_state(ioim, bfa_ioim_sm_uninit)); - - bfa_assert_fp(list_empty(&ioim->sgpg_q) || - (ioim->nsges > BFI_SGE_INLINE)); - if (ioim->nsgpgs > 0) bfa_sgpg_mfree(ioim->bfa, &ioim->sgpg_q, ioim->nsgpgs); @@ -2638,8 +2617,6 @@ bfa_ioim_free(struct bfa_ioim_s *ioim) void bfa_ioim_start(struct bfa_ioim_s *ioim) { - bfa_trc_fp(ioim->bfa, ioim->iotag); - bfa_ioim_cb_profile_start(ioim->fcpim, ioim); /* diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c index d33e93a7a672..6577d0d922f6 100644 --- a/drivers/scsi/bfa/bfa_svc.c +++ b/drivers/scsi/bfa/bfa_svc.c @@ -4670,8 +4670,6 @@ bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs) struct bfa_sgpg_s *hsgpg; int i; - bfa_trc_fp(bfa, nsgpgs); - if (mod->free_sgpgs < nsgpgs) return BFA_STATUS_ENOMEM; @@ -4691,8 +4689,6 @@ bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpg) struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa); struct bfa_sgpg_wqe_s *wqe; - bfa_trc_fp(bfa, nsgpg); - mod->free_sgpgs += nsgpg; WARN_ON(mod->free_sgpgs > mod->num_sgpgs); diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index 4e94d28ae328..44524cf55d33 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -1166,7 +1166,6 @@ bfad_intx(int irq, void *dev_id) spin_lock_irqsave(&bfad->bfad_lock, flags); bfa_comp_free(&bfad->bfa, &doneq); spin_unlock_irqrestore(&bfad->bfad_lock, flags); - bfa_trc_fp(bfad, irq); } return IRQ_HANDLED; diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index f0bcda8f077f..c2b36179e8e8 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c @@ -1174,7 +1174,6 @@ bfad_im_queuecommand_lck(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd } cmnd->host_scribble = (char *)hal_io; - bfa_trc_fp(bfad, hal_io->iotag); bfa_ioim_start(hal_io); spin_unlock_irqrestore(&bfad->bfad_lock, flags); -- cgit v1.2.3-59-g8ed1b From 8f4bfadd200477acb6dcf41a45919dd37d01a6db Mon Sep 17 00:00:00 2001 From: Jing Huang Date: Sun, 26 Dec 2010 21:50:10 -0800 Subject: [SCSI] bfa: remove unused defintions and misc cleanups This patch removes unused functions, data strucutres, and definitions. It also includes misc comment and formatting cleanups. Signed-off-by: Jing Huang Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa.h | 2 - drivers/scsi/bfa/bfa_core.c | 12 - drivers/scsi/bfa/bfa_fc.h | 588 ++++++++++-------------------------------- drivers/scsi/bfa/bfa_fcpim.c | 2 +- drivers/scsi/bfa/bfa_ioc.c | 38 +-- drivers/scsi/bfa/bfa_ioc.h | 9 - drivers/scsi/bfa/bfa_ioc_cb.c | 9 +- drivers/scsi/bfa/bfa_ioc_ct.c | 6 +- drivers/scsi/bfa/bfa_svc.c | 6 +- 9 files changed, 158 insertions(+), 514 deletions(-) diff --git a/drivers/scsi/bfa/bfa.h b/drivers/scsi/bfa/bfa.h index 56a227b023ae..7be6b5a8114b 100644 --- a/drivers/scsi/bfa/bfa.h +++ b/drivers/scsi/bfa/bfa.h @@ -334,8 +334,6 @@ void bfa_hwct_msix_get_rme_range(struct bfa_s *bfa, u32 *start, void bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns); wwn_t bfa_iocfc_get_pwwn(struct bfa_s *bfa); wwn_t bfa_iocfc_get_nwwn(struct bfa_s *bfa); -void bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa, - struct bfa_boot_pbc_s *pbcfg); int bfa_iocfc_get_pbc_vports(struct bfa_s *bfa, struct bfi_pbc_vport_s *pbc_vport); diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c index d6c7e05ae4ce..1cd5c8b0618d 100644 --- a/drivers/scsi/bfa/bfa_core.c +++ b/drivers/scsi/bfa/bfa_core.c @@ -998,18 +998,6 @@ bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns) memcpy(wwns, cfgrsp->bootwwns.wwn, sizeof(cfgrsp->bootwwns.wwn)); } -void -bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa, struct bfa_boot_pbc_s *pbcfg) -{ - struct bfa_iocfc_s *iocfc = &bfa->iocfc; - struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp; - - pbcfg->enable = cfgrsp->pbc_cfg.boot_enabled; - pbcfg->nbluns = cfgrsp->pbc_cfg.nbluns; - pbcfg->speed = cfgrsp->pbc_cfg.port_speed; - memcpy(pbcfg->pblun, cfgrsp->pbc_cfg.blun, sizeof(pbcfg->pblun)); -} - int bfa_iocfc_get_pbc_vports(struct bfa_s *bfa, struct bfi_pbc_vport_s *pbc_vport) { diff --git a/drivers/scsi/bfa/bfa_fc.h b/drivers/scsi/bfa/bfa_fc.h index 0d04ba9574f9..8e764fae8dc9 100644 --- a/drivers/scsi/bfa/bfa_fc.h +++ b/drivers/scsi/bfa/bfa_fc.h @@ -24,7 +24,6 @@ typedef u64 wwn_t; #define WWN_NULL (0) #define FC_SYMNAME_MAX 256 /* max name server symbolic name size */ -#define FC_ALPA_MAX 128 #pragma pack(1) @@ -39,7 +38,6 @@ struct mac_s { u8 mac[MAC_ADDRLEN]; }; struct scsi_cdb_s { u8 scsi_cdb[SCSI_MAX_CDBLEN]; }; -#define scsi_cdb_t struct scsi_cdb_s /* ------------------------------------------------------------ * SCSI status byte values @@ -74,34 +72,19 @@ struct fchs_s { u32 cs_ctl:8; /* class specific control */ u32 s_id:24; /* source identifier */ - u32 type:8; /* data structure type */ + u32 type:8; /* data structure type */ u32 f_ctl:24; /* initial frame control */ - u8 seq_id; /* sequence identifier */ - u8 df_ctl; /* data field control */ + u8 seq_id; /* sequence identifier */ + u8 df_ctl; /* data field control */ u16 seq_cnt; /* sequence count */ - __be16 ox_id; /* originator exchange ID */ - u16 rx_id; /* responder exchange ID */ + __be16 ox_id; /* originator exchange ID */ + u16 rx_id; /* responder exchange ID */ u32 ro; /* relative offset */ }; -#define FC_SOF_LEN 4 -#define FC_EOF_LEN 4 -#define FC_CRC_LEN 4 - -/* - * Fibre Channel BB_E Header Structure - */ -struct fcbbehs_s { - u16 ver_rsvd; - u32 rsvd[2]; - u32 rsvd__sof; -}; - -#define FC_SEQ_ID_MAX 256 - /* * routing bit definitions */ @@ -147,22 +130,6 @@ enum { FC_CAT_CMD_STATUS = 0x7, /* Command Status */ }; -/* - * information category for Link Control - */ -enum { - FC_CAT_ACK_1 = 0x00, - FC_CAT_ACK_0_N = 0x01, - FC_CAT_P_RJT = 0x02, - FC_CAT_F_RJT = 0x03, - FC_CAT_P_BSY = 0x04, - FC_CAT_F_BSY_DATA = 0x05, - FC_CAT_F_BSY_LINK_CTL = 0x06, - FC_CAT_F_LCR = 0x07, - FC_CAT_NTY = 0x08, - FC_CAT_END = 0x09, -}; - /* * Type Field Definitions. FC-PH Section 18.5 pg. 165 */ @@ -181,10 +148,6 @@ enum { FC_TYPE_MAX = 256, /* 256 FC-4 types */ }; -struct fc_fc4types_s { - u8 bits[FC_TYPE_MAX / 8]; -}; - /* * Frame Control Definitions. FC-PH Table-45. pg. 168 */ @@ -287,7 +250,6 @@ enum { FC_ELS_AUTH = 0x90, /* Authentication. Ref FC-SP */ FC_ELS_RFCN = 0x97, /* Request Fabric Change Notification. Ref *FC-SP */ - }; /* @@ -313,12 +275,12 @@ enum { * FC-PH-x. Figure-76. pg. 308. */ struct fc_plogi_csp_s { - u8 verhi; /* FC-PH high version */ - u8 verlo; /* FC-PH low version */ - __be16 bbcred; /* BB_Credit */ + u8 verhi; /* FC-PH high version */ + u8 verlo; /* FC-PH low version */ + __be16 bbcred; /* BB_Credit */ #ifdef __BIG_ENDIAN - u8 ciro:1, /* continuously increasing RO */ + u8 ciro:1, /* continuously increasing RO */ rro:1, /* random relative offset */ npiv_supp:1, /* NPIV supported */ port_type:1, /* N_Port/F_port */ @@ -327,7 +289,7 @@ struct fc_plogi_csp_s { vvl_info:1, /* VVL Info included */ reserved1:1; - u8 hg_supp:1, + u8 hg_supp:1, query_dbc:1, security:1, sync_cap:1, @@ -336,7 +298,7 @@ struct fc_plogi_csp_s { cisc:1, /* continuously increasing seq count */ payload:1; #else - u8 reserved2:2, + u8 reserved2:2, resolution:1, /* ms/ns ED_TOV resolution */ altbbcred:1, /* alternate BB_Credit */ port_type:1, /* N_Port/F_port */ @@ -344,7 +306,7 @@ struct fc_plogi_csp_s { rro:1, /* random relative offset */ ciro:1; /* continuously increasing RO */ - u8 payload:1, + u8 payload:1, cisc:1, /* continuously increasing seq count */ dh_dup_supp:1, r_t_tov:1, @@ -353,13 +315,10 @@ struct fc_plogi_csp_s { query_dbc:1, hg_supp:1; #endif - - __be16 rxsz; /* recieve data_field size */ - - __be16 conseq; - __be16 ro_bitmap; - - __be32 e_d_tov; + __be16 rxsz; /* recieve data_field size */ + __be16 conseq; + __be16 ro_bitmap; + __be32 e_d_tov; }; /* @@ -370,9 +329,8 @@ struct fc_plogi_clp_s { #ifdef __BIG_ENDIAN u32 class_valid:1; u32 intermix:1; /* class intermix supported if set =1. - * valid only for class1. Reserved for - * class2 & class3 - */ + * valid only for class1. Reserved for + * class2 & class3 */ u32 reserved1:2; u32 sequential:1; u32 reserved2:3; @@ -381,12 +339,10 @@ struct fc_plogi_clp_s { u32 sequential:1; u32 reserved1:2; u32 intermix:1; /* class intermix supported if set =1. - * valid only for class1. Reserved for - * class2 & class3 - */ + * valid only for class1. Reserved for + * class2 & class3 */ u32 class_valid:1; #endif - u32 reserved3:24; u32 reserved4:16; @@ -394,7 +350,7 @@ struct fc_plogi_clp_s { u32 reserved5:8; u32 conseq:8; - u32 e2e_credit:16; /* end to end credit */ + u32 e2e_credit:16; /* end to end credit */ u32 reserved7:8; u32 ospx:8; @@ -408,24 +364,24 @@ struct fc_plogi_clp_s { * PLOGI els command and reply payload */ struct fc_logi_s { - struct fc_els_cmd_s els_cmd; /* ELS command code */ - struct fc_plogi_csp_s csp; /* common service params */ - wwn_t port_name; - wwn_t node_name; - struct fc_plogi_clp_s class1; /* class 1 service parameters */ - struct fc_plogi_clp_s class2; /* class 2 service parameters */ - struct fc_plogi_clp_s class3; /* class 3 service parameters */ - struct fc_plogi_clp_s class4; /* class 4 service parameters */ - u8 vvl[16]; /* vendor version level */ + struct fc_els_cmd_s els_cmd; /* ELS command code */ + struct fc_plogi_csp_s csp; /* common service params */ + wwn_t port_name; + wwn_t node_name; + struct fc_plogi_clp_s class1; /* class 1 service parameters */ + struct fc_plogi_clp_s class2; /* class 2 service parameters */ + struct fc_plogi_clp_s class3; /* class 3 service parameters */ + struct fc_plogi_clp_s class4; /* class 4 service parameters */ + u8 vvl[16]; /* vendor version level */ }; /* * LOGO els command payload */ struct fc_logo_s { - struct fc_els_cmd_s els_cmd; /* ELS command code */ - u32 res1:8; - u32 nport_id:24; /* N_Port identifier of source */ + struct fc_els_cmd_s els_cmd; /* ELS command code */ + u32 res1:8; + u32 nport_id:24; /* N_Port identifier of source */ wwn_t orig_port_name; /* Port name of the LOGO originator */ }; @@ -434,12 +390,12 @@ struct fc_logo_s { */ struct fc_adisc_s { struct fc_els_cmd_s els_cmd; /* ELS command code */ - u32 res1:8; - u32 orig_HA:24; /* originator hard address */ - wwn_t orig_port_name; /* originator port name */ - wwn_t orig_node_name; /* originator node name */ - u32 res2:8; - u32 nport_id:24; /* originator NPortID */ + u32 res1:8; + u32 orig_HA:24; /* originator hard address */ + wwn_t orig_port_name; /* originator port name */ + wwn_t orig_node_name; /* originator node name */ + u32 res2:8; + u32 nport_id:24; /* originator NPortID */ }; /* @@ -465,7 +421,7 @@ struct fc_exch_status_blk_s { struct fc_res_s { struct fc_els_cmd_s els_cmd; /* ELS command code */ u32 res1:8; - u32 nport_id:24; /* N_Port identifier of source */ + u32 nport_id:24; /* N_Port identifier of source */ u32 oxid:16; u32 rxid:16; u8 assoc_hdr[32]; @@ -511,8 +467,8 @@ struct fc_rec_acc_s { u32 orig_id:24; /* N_Port id of exchange originator */ u32 res2:8; u32 resp_id:24; /* N_Port id of exchange responder */ - u32 count; /* data transfer count */ - u32 e_stat; /* exchange status */ + u32 count; /* data transfer count */ + u32 e_stat; /* exchange status */ }; /* @@ -611,17 +567,13 @@ struct fc_prlo_params_page_s { u32 type:8; u32 type_ext:8; #ifdef __BIG_ENDIAN - u32 opa_valid:1; /* originator process associator - * valid - */ + u32 opa_valid:1; /* originator process associator valid */ u32 rpa_valid:1; /* responder process associator valid */ u32 res1:14; #else u32 res1:14; u32 rpa_valid:1; /* responder process associator valid */ - u32 opa_valid:1; /* originator process associator - * valid - */ + u32 opa_valid:1; /* originator process associator valid */ #endif u32 orig_process_assc; u32 resp_process_assc; @@ -647,17 +599,13 @@ struct fc_prlo_acc_params_page_s { u32 type_ext:8; #ifdef __BIG_ENDIAN - u32 opa_valid:1; /* originator process associator - * valid - */ + u32 opa_valid:1; /* originator process associator valid */ u32 rpa_valid:1; /* responder process associator valid */ u32 res1:14; #else u32 res1:14; u32 rpa_valid:1; /* responder process associator valid */ - u32 opa_valid:1; /* originator process associator - * valid - */ + u32 opa_valid:1; /* originator process associator valid */ #endif u32 orig_process_assc; u32 resp_process_assc; @@ -714,9 +662,9 @@ enum { * LS_RJT els reply payload */ struct fc_ls_rjt_s { - struct fc_els_cmd_s els_cmd; /* ELS command code */ + struct fc_els_cmd_s els_cmd; /* ELS command code */ u32 res1:8; - u32 reason_code:8; /* Reason code for reject */ + u32 reason_code:8; /* Reason code for reject */ u32 reason_code_expl:8; /* Reason code explanation */ u32 vendor_unique:8; /* Vendor specific */ }; @@ -778,12 +726,12 @@ struct fc_rrq_s { */ struct fc_ba_acc_s { u32 seq_id_valid:8; /* set to 0x00 for Abort Exchange */ - u32 seq_id:8; /* invalid for Abort Exchange */ + u32 seq_id:8; /* invalid for Abort Exchange */ u32 res2:16; - u32 ox_id:16; /* OX_ID from ABTS frame */ - u32 rx_id:16; /* RX_ID from ABTS frame */ + u32 ox_id:16; /* OX_ID from ABTS frame */ + u32 rx_id:16; /* RX_ID from ABTS frame */ u32 low_seq_cnt:16; /* set to 0x0000 for Abort Exchange */ - u32 high_seq_cnt:16;/* set to 0xFFFF for Abort Exchange */ + u32 high_seq_cnt:16; /* set to 0xFFFF for Abort Exchange */ }; /* @@ -793,15 +741,15 @@ struct fc_ba_rjt_s { u32 res1:8; /* Reserved */ u32 reason_code:8; /* reason code for reject */ u32 reason_expl:8; /* reason code explanation */ - u32 vendor_unique:8;/* vendor unique reason code,set to 0 */ + u32 vendor_unique:8; /* vendor unique reason code,set to 0 */ }; /* * TPRLO logout parameter page */ struct fc_tprlo_params_page_s { -u32 type:8; -u32 type_ext:8; + u32 type:8; + u32 type_ext:8; #ifdef __BIG_ENDIAN u32 opa_valid:1; @@ -863,16 +811,16 @@ enum fc_rscn_format { }; struct fc_rscn_event_s { - u32 format:2; - u32 qualifier:4; - u32 resvd:2; - u32 portid:24; + u32 format:2; + u32 qualifier:4; + u32 resvd:2; + u32 portid:24; }; struct fc_rscn_pl_s { - u8 command; - u8 pagelen; - __be16 payldlen; + u8 command; + u8 pagelen; + __be16 payldlen; struct fc_rscn_event_s event[1]; }; @@ -886,7 +834,6 @@ struct fc_echo_s { /* * RNID els command */ - #define RNID_NODEID_DATA_FORMAT_COMMON 0x00 #define RNID_NODEID_DATA_FORMAT_FCP3 0x08 #define RNID_NODEID_DATA_FORMAT_DISCOVERY 0xDF @@ -919,15 +866,15 @@ struct fc_rnid_cmd_s { */ struct fc_rnid_common_id_data_s { - wwn_t port_name; + wwn_t port_name; wwn_t node_name; }; struct fc_rnid_general_topology_data_s { u32 vendor_unique[4]; - __be32 asso_type; + __be32 asso_type; u32 phy_port_num; - __be32 num_attached_nodes; + __be32 num_attached_nodes; u32 node_mgmt:8; u32 ip_version:8; u32 udp_tcp_port_num:16; @@ -979,59 +926,17 @@ enum fc_rpsc_op_speed { RPSC_OP_SPEED_8G = 0x0800, RPSC_OP_SPEED_16G = 0x0400, - RPSC_OP_SPEED_NOT_EST = 0x0001, /*! speed not established */ + RPSC_OP_SPEED_NOT_EST = 0x0001, /* speed not established */ }; struct fc_rpsc_speed_info_s { - __be16 port_speed_cap; /*! see enum fc_rpsc_speed_cap */ - __be16 port_op_speed; /*! see enum fc_rpsc_op_speed */ -}; - -enum link_e2e_beacon_subcmd { - LINK_E2E_BEACON_ON = 1, - LINK_E2E_BEACON_OFF = 2 -}; - -enum beacon_type { - BEACON_TYPE_NORMAL = 1, /*! Normal Beaconing. Green */ - BEACON_TYPE_WARN = 2, /*! Warning Beaconing. Yellow/Amber */ - BEACON_TYPE_CRITICAL = 3 /*! Critical Beaconing. Red */ -}; - -struct link_e2e_beacon_param_s { - u8 beacon_type; /* Beacon Type. See enum beacon_type */ - u8 beacon_frequency; - /* Beacon frequency. Number of blinks - * per 10 seconds - */ - u16 beacon_duration;/* Beacon duration (in Seconds). The - * command operation should be - * terminated at the end of this - * timeout value. - * - * Ignored if diag_sub_cmd is - * LINK_E2E_BEACON_OFF. - * - * If 0, beaconing will continue till a - * BEACON OFF request is received - */ -}; - -/* - * Link E2E beacon request/good response format. - * For LS_RJTs use struct fc_ls_rjt_s - */ -struct link_e2e_beacon_req_s { - u32 ls_code; /*! FC_ELS_E2E_LBEACON in requests * - *or FC_ELS_ACC in good replies */ - u32 ls_sub_cmd; /*! See enum link_e2e_beacon_subcmd */ - struct link_e2e_beacon_param_s beacon_parm; + __be16 port_speed_cap; /* see enum fc_rpsc_speed_cap */ + __be16 port_op_speed; /* see enum fc_rpsc_op_speed */ }; /* * If RPSC request is sent to the Domain Controller, the request is for - * all the ports within that domain (TODO - I don't think FOS implements - * this...). + * all the ports within that domain. */ struct fc_rpsc_cmd_s { struct fc_els_cmd_s els_cmd; @@ -1057,7 +962,7 @@ struct fc_rpsc2_cmd_s { struct fc_els_cmd_s els_cmd; __be32 token; u16 resvd; - __be16 num_pids; /* Number of pids in the request */ + __be16 num_pids; /* Number of pids in the request */ struct { u32 rsvd1:8; u32 pid:24; /* port identifier */ @@ -1071,16 +976,17 @@ enum fc_rpsc2_port_type { RPSC2_PORT_TYPE_NPIV_PORT = 0x5f, RPSC2_PORT_TYPE_NPORT_TRUNK = 0x6f, }; + /* * RPSC2 portInfo entry structure */ struct fc_rpsc2_port_info_s { - __be32 pid; /* PID */ + __be32 pid; /* PID */ u16 resvd1; - __be16 index; /* port number / index */ + __be16 index; /* port number / index */ u8 resvd2; - u8 type; /* port type N/NL/... */ - __be16 speed; /* port Operating Speed */ + u8 type; /* port type N/NL/... */ + __be16 speed; /* port Operating Speed */ }; /* @@ -1089,8 +995,8 @@ struct fc_rpsc2_port_info_s { struct fc_rpsc2_acc_s { u8 els_cmd; u8 resvd; - __be16 num_pids; /* Number of pids in the request */ - struct fc_rpsc2_port_info_s port_info[1]; /* port information */ + __be16 num_pids; /* Number of pids in the request */ + struct fc_rpsc2_port_info_s port_info[1]; /* port information */ }; /* @@ -1109,18 +1015,14 @@ struct fc_symname_s { u8 symname[FC_SYMNAME_MAX]; }; -struct fc_alpabm_s { - u8 alpa_bm[FC_ALPA_MAX / 8]; -}; - /* * protocol default timeout values */ -#define FC_ED_TOV 2 -#define FC_REC_TOV (FC_ED_TOV + 1) -#define FC_RA_TOV 10 -#define FC_ELS_TOV (2 * FC_RA_TOV) -#define FC_FCCT_TOV (3 * FC_RA_TOV) +#define FC_ED_TOV 2 +#define FC_REC_TOV (FC_ED_TOV + 1) +#define FC_RA_TOV 10 +#define FC_ELS_TOV (2 * FC_RA_TOV) +#define FC_FCCT_TOV (3 * FC_RA_TOV) /* * virtual fabric related defines @@ -1155,19 +1057,6 @@ enum { FCP_SRR = 0x14000000, /* Sequence Retransmission Request */ }; -/* - * SRR FC-4 LS payload - */ -struct fc_srr_s { - u32 ls_cmd; - u32 ox_id:16; /* ox-id */ - u32 rx_id:16; /* rx-id */ - u32 ro; /* relative offset */ - u32 r_ctl:8; /* R_CTL for I.U. */ - u32 res:24; -}; - - /* * FCP_CMND definitions */ @@ -1175,30 +1064,27 @@ struct fc_srr_s { #define FCP_CMND_LUN_LEN 8 struct fcp_cmnd_s { - struct scsi_lun lun; /* 64-bit LU number */ - u8 crn; /* command reference number */ + struct scsi_lun lun; /* 64-bit LU number */ + u8 crn; /* command reference number */ #ifdef __BIG_ENDIAN - u8 resvd:1, + u8 resvd:1, priority:4, /* FCP-3: SAM-3 priority */ taskattr:3; /* scsi task attribute */ #else - u8 taskattr:3, /* scsi task attribute */ + u8 taskattr:3, /* scsi task attribute */ priority:4, /* FCP-3: SAM-3 priority */ resvd:1; #endif - u8 tm_flags; /* task management flags */ + u8 tm_flags; /* task management flags */ #ifdef __BIG_ENDIAN - u8 addl_cdb_len:6, /* additional CDB length words */ + u8 addl_cdb_len:6, /* additional CDB length words */ iodir:2; /* read/write FCP_DATA IUs */ #else - u8 iodir:2, /* read/write FCP_DATA IUs */ + u8 iodir:2, /* read/write FCP_DATA IUs */ addl_cdb_len:6; /* additional CDB length */ #endif - scsi_cdb_t cdb; + struct scsi_cdb_s cdb; - /* - * !!! additional cdb bytes follows here!!! - */ __be32 fcp_dl; /* bytes to be transferred */ }; @@ -1209,21 +1095,10 @@ struct fcp_cmnd_s { * struct fcp_cmnd_s .iodir field values */ enum fcp_iodir { - FCP_IODIR_NONE = 0, + FCP_IODIR_NONE = 0, FCP_IODIR_WRITE = 1, - FCP_IODIR_READ = 2, - FCP_IODIR_RW = 3, -}; - -/* - * Task attribute field - */ -enum { - FCP_TASK_ATTR_SIMPLE = 0, - FCP_TASK_ATTR_HOQ = 1, - FCP_TASK_ATTR_ORDERED = 2, - FCP_TASK_ATTR_ACA = 4, - FCP_TASK_ATTR_UNTAGGED = 5, /* obsolete in FCP-3 */ + FCP_IODIR_READ = 2, + FCP_IODIR_RW = 3, }; /* @@ -1237,59 +1112,41 @@ enum fcp_tm_cmnd { FCP_TM_CLEAR_ACA = BIT(6), }; -/* - * FCP_XFER_RDY IU defines - */ -struct fcp_xfer_rdy_s { - u32 data_ro; - u32 burst_len; - u32 reserved; -}; - /* * FCP_RSP residue flags */ enum fcp_residue { - FCP_NO_RESIDUE = 0, /* no residue */ - FCP_RESID_OVER = 1, /* more data left that was not sent */ - FCP_RESID_UNDER = 2, /* less data than requested */ -}; - -enum { - FCP_RSPINFO_GOOD = 0, - FCP_RSPINFO_DATALEN_MISMATCH = 1, - FCP_RSPINFO_CMND_INVALID = 2, - FCP_RSPINFO_ROLEN_MISMATCH = 3, - FCP_RSPINFO_TM_NOT_SUPP = 4, - FCP_RSPINFO_TM_FAILED = 5, + FCP_NO_RESIDUE = 0, /* no residue */ + FCP_RESID_OVER = 1, /* more data left that was not sent */ + FCP_RESID_UNDER = 2, /* less data than requested */ }; struct fcp_rspinfo_s { u32 res0:24; - u32 rsp_code:8; /* response code (as above) */ + u32 rsp_code:8; /* response code (as above) */ u32 res1; }; struct fcp_resp_s { - u32 reserved[2]; /* 2 words reserved */ + u32 reserved[2]; /* 2 words reserved */ u16 reserved2; #ifdef __BIG_ENDIAN u8 reserved3:3; u8 fcp_conf_req:1; /* FCP_CONF is requested */ u8 resid_flags:2; /* underflow/overflow */ - u8 sns_len_valid:1;/* sense len is valid */ - u8 rsp_len_valid:1;/* response len is valid */ + u8 sns_len_valid:1; /* sense len is valid */ + u8 rsp_len_valid:1; /* response len is valid */ #else - u8 rsp_len_valid:1;/* response len is valid */ - u8 sns_len_valid:1;/* sense len is valid */ + u8 rsp_len_valid:1; /* response len is valid */ + u8 sns_len_valid:1; /* sense len is valid */ u8 resid_flags:2; /* underflow/overflow */ u8 fcp_conf_req:1; /* FCP_CONF is requested */ u8 reserved3:3; #endif - u8 scsi_status; /* one byte SCSI status */ - u32 residue; /* residual data bytes */ - u32 sns_len; /* length od sense info */ - u32 rsp_len; /* length of response info */ + u8 scsi_status; /* one byte SCSI status */ + u32 residue; /* residual data bytes */ + u32 sns_len; /* length od sense info */ + u32 rsp_len; /* length of response info */ }; #define fcp_snslen(__fcprsp) ((__fcprsp)->sns_len_valid ? \ @@ -1299,12 +1156,6 @@ struct fcp_resp_s { #define fcp_rspinfo(__fcprsp) ((struct fcp_rspinfo_s *)((__fcprsp) + 1)) #define fcp_snsinfo(__fcprsp) (((u8 *)fcp_rspinfo(__fcprsp)) + \ fcp_rsplen(__fcprsp)) - -struct fcp_cmnd_fr_s { - struct fchs_s fchs; - struct fcp_cmnd_s fcp; -}; - /* * CT */ @@ -1378,7 +1229,7 @@ enum { CT_RSN_LOGICAL_BUSY = 0x05, CT_RSN_PROTO_ERR = 0x07, CT_RSN_UNABLE_TO_PERF = 0x09, - CT_RSN_NOT_SUPP = 0x0B, + CT_RSN_NOT_SUPP = 0x0B, CT_RSN_SERVER_NOT_AVBL = 0x0D, CT_RSN_SESSION_COULD_NOT_BE_ESTBD = 0x0E, CT_RSN_VENDOR_SPECIFIC = 0xFF, @@ -1418,10 +1269,10 @@ enum { * defintions for the explanation code for all servers */ enum { - CT_EXP_AUTH_EXCEPTION = 0xF1, - CT_EXP_DB_FULL = 0xF2, - CT_EXP_DB_EMPTY = 0xF3, - CT_EXP_PROCESSING_REQ = 0xF4, + CT_EXP_AUTH_EXCEPTION = 0xF1, + CT_EXP_DB_FULL = 0xF2, + CT_EXP_DB_EMPTY = 0xF3, + CT_EXP_PROCESSING_REQ = 0xF4, CT_EXP_UNABLE_TO_VERIFY_CONN = 0xF5, CT_EXP_DEVICES_NOT_IN_CMN_ZONE = 0xF6 }; @@ -1445,7 +1296,7 @@ enum { GS_RFF_ID = 0x021F, /* Register FC4 Feature */ }; -struct fcgs_id_req_s{ +struct fcgs_id_req_s { u32 rsvd:8; u32 dap:24; /* port identifier */ }; @@ -1459,7 +1310,7 @@ struct fcgs_gidpn_req_s { struct fcgs_gidpn_resp_s { u32 rsvd:8; - u32 dap:24; /* port identifier */ + u32 dap:24; /* port identifier */ }; /* @@ -1474,16 +1325,15 @@ struct fcgs_rftid_req_s { /* * RFF_ID : Register FC4 features. */ - #define FC_GS_FCP_FC4_FEATURE_INITIATOR 0x02 #define FC_GS_FCP_FC4_FEATURE_TARGET 0x01 struct fcgs_rffid_req_s { - u32 rsvd:8; - u32 dap:24; /* port identifier */ - u32 rsvd1:16; - u32 fc4ftr_bits:8; /* fc4 feature bits */ - u32 fc4_type:8; /* corresponding FC4 Type */ + u32 rsvd:8; + u32 dap:24; /* port identifier */ + u32 rsvd1:16; + u32 fc4ftr_bits:8; /* fc4 feature bits */ + u32 fc4_type:8; /* corresponding FC4 Type */ }; /* @@ -1494,16 +1344,16 @@ struct fcgs_gidft_req_s { u8 domain_id; /* domain, 0 - all fabric */ u8 area_id; /* area, 0 - whole domain */ u8 fc4_type; /* FC_TYPE_FCP for SCSI devices */ -}; /* GID_FT Request */ +}; /* * GID_FT Response */ struct fcgs_gidft_resp_s { - u8 last:1; /* last port identifier flag */ - u8 reserved:7; - u32 pid:24; /* port identifier */ -}; /* GID_FT Response */ + u8 last:1; /* last port identifier flag */ + u8 reserved:7; + u32 pid:24; /* port identifier */ +}; /* * RSPN_ID @@ -1511,8 +1361,8 @@ struct fcgs_gidft_resp_s { struct fcgs_rspnid_req_s { u32 rsvd:8; u32 dap:24; /* port identifier */ - u8 spn_len; /* symbolic port name length */ - u8 spn[256]; /* symbolic port name */ + u8 spn_len; /* symbolic port name length */ + u8 spn[256]; /* symbolic port name */ }; /* @@ -1521,7 +1371,7 @@ struct fcgs_rspnid_req_s { struct fcgs_rpnid_req_s { u32 rsvd:8; u32 port_id:24; - wwn_t port_name; + wwn_t port_name; }; /* @@ -1530,7 +1380,7 @@ struct fcgs_rpnid_req_s { struct fcgs_rnnid_req_s { u32 rsvd:8; u32 port_id:24; - wwn_t node_name; + wwn_t node_name; }; /* @@ -1564,8 +1414,8 @@ struct fcgs_ganxt_req_s { * GA_NXT Response */ struct fcgs_ganxt_rsp_s { - u32 port_type:8; /* Port Type */ - u32 port_id:24; /* Port Identifier */ + u32 port_type:8; /* Port Type */ + u32 port_id:24; /* Port Identifier */ wwn_t port_name; /* Port Name */ u8 spn_len; /* Length of Symbolic Port Name */ char spn[255]; /* Symbolic Port Name */ @@ -1574,18 +1424,13 @@ struct fcgs_ganxt_rsp_s { char snn[255]; /* Symbolic Node Name */ u8 ipa[8]; /* Initial Process Associator */ u8 ip[16]; /* IP Address */ - u32 cos; /* Class of Service */ - u32 fc4types[8]; /* FC-4 TYPEs */ - wwn_t fabric_port_name; - /* Fabric Port Name */ - u32 rsvd:8; /* Reserved */ - u32 hard_addr:24; /* Hard Address */ + u32 cos; /* Class of Service */ + u32 fc4types[8]; /* FC-4 TYPEs */ + wwn_t fabric_port_name; /* Fabric Port Name */ + u32 rsvd:8; /* Reserved */ + u32 hard_addr:24; /* Hard Address */ }; -/* - * Fabric Config Server - */ - /* * Command codes for Fabric Configuration Server */ @@ -1596,160 +1441,10 @@ enum { GS_FC_PING_CMD = 0x0401, /* GS FC Ping */ }; -/* - * Source or Destination Port Tags. - */ -enum { - GS_FTRACE_TAG_NPORT_ID = 1, - GS_FTRACE_TAG_NPORT_NAME = 2, -}; - -/* -* Port Value : Could be a Port id or wwn - */ -union fcgs_port_val_u { - u32 nport_id; - wwn_t nport_wwn; -}; - -#define GS_FTRACE_MAX_HOP_COUNT 20 -#define GS_FTRACE_REVISION 1 - -/* - * Ftrace Related Structures. - */ - -/* - * STR (Switch Trace) Reject Reason Codes. From FC-SW. - */ -enum { - GS_FTRACE_STR_CMD_COMPLETED_SUCC = 0, - GS_FTRACE_STR_CMD_NOT_SUPP_IN_NEXT_SWITCH, - GS_FTRACE_STR_NO_RESP_FROM_NEXT_SWITCH, - GS_FTRACE_STR_MAX_HOP_CNT_REACHED, - GS_FTRACE_STR_SRC_PORT_NOT_FOUND, - GS_FTRACE_STR_DST_PORT_NOT_FOUND, - GS_FTRACE_STR_DEVICES_NOT_IN_COMMON_ZONE, - GS_FTRACE_STR_NO_ROUTE_BW_PORTS, - GS_FTRACE_STR_NO_ADDL_EXPLN, - GS_FTRACE_STR_FABRIC_BUSY, - GS_FTRACE_STR_FABRIC_BUILD_IN_PROGRESS, - GS_FTRACE_STR_VENDOR_SPECIFIC_ERR_START = 0xf0, - GS_FTRACE_STR_VENDOR_SPECIFIC_ERR_END = 0xff, -}; - -/* - * Ftrace Request - */ -struct fcgs_ftrace_req_s { - u32 revision; - u16 src_port_tag; /* Source Port tag */ - u16 src_port_len; /* Source Port len */ - union fcgs_port_val_u src_port_val; /* Source Port value */ - u16 dst_port_tag; /* Destination Port tag */ - u16 dst_port_len; /* Destination Port len */ - union fcgs_port_val_u dst_port_val; /* Destination Port value */ - u32 token; - u8 vendor_id[8]; /* T10 Vendor Identifier */ - u8 vendor_info[8]; /* Vendor specific Info */ - u32 max_hop_cnt; /* Max Hop Count */ -}; - -/* - * Path info structure - */ -struct fcgs_ftrace_path_info_s { - wwn_t switch_name; /* Switch WWN */ - u32 domain_id; - wwn_t ingress_port_name; /* Ingress ports wwn */ - u32 ingress_phys_port_num; /* Ingress ports physical port - * number - */ - wwn_t egress_port_name; /* Ingress ports wwn */ - u32 egress_phys_port_num; /* Ingress ports physical port - * number - */ -}; - -/* - * Ftrace Acc Response - */ -struct fcgs_ftrace_resp_s { - u32 revision; - u32 token; - u8 vendor_id[8]; /* T10 Vendor Identifier */ - u8 vendor_info[8]; /* Vendor specific Info */ - u32 str_rej_reason_code; /* STR Reject Reason Code */ - u32 num_path_info_entries; /* No. of path info entries */ - /* - * path info entry/entries. - */ - struct fcgs_ftrace_path_info_s path_info[1]; - -}; - -/* -* Fabric Config Server : FCPing - */ - -/* - * FC Ping Request - */ -struct fcgs_fcping_req_s { - u32 revision; - u16 port_tag; - u16 port_len; /* Port len */ - union fcgs_port_val_u port_val; /* Port value */ - u32 token; -}; - -/* - * FC Ping Response - */ -struct fcgs_fcping_resp_s { - u32 token; -}; - -/* - * Command codes for zone server query. - */ -enum { - ZS_GZME = 0x0124, /* Get zone member extended */ -}; - -/* - * ZS GZME request - */ -#define ZS_GZME_ZNAMELEN 32 -struct zs_gzme_req_s { - u8 znamelen; - u8 rsvd[3]; - u8 zname[ZS_GZME_ZNAMELEN]; -}; - -enum zs_mbr_type { - ZS_MBR_TYPE_PWWN = 1, - ZS_MBR_TYPE_DOMPORT = 2, - ZS_MBR_TYPE_PORTID = 3, - ZS_MBR_TYPE_NWWN = 4, -}; - -struct zs_mbr_wwn_s { - u8 mbr_type; - u8 rsvd[3]; - wwn_t wwn; -}; - -struct zs_query_resp_s { - u32 nmbrs; /* number of zone members */ - struct zs_mbr_wwn_s mbr[1]; -}; - /* * GMAL Command ( Get ( interconnect Element) Management Address List) * To retrieve the IP Address of a Switch. */ - #define CT_GMAL_RESP_PREFIX_TELNET "telnet://" #define CT_GMAL_RESP_PREFIX_HTTP "http://" @@ -1773,9 +1468,6 @@ struct fcgs_gmal_entry_s { u8 ip_addr[248]; }; -/* - * FDMI - */ /* * FDMI Command Codes */ @@ -1872,8 +1564,8 @@ struct fdmi_hba_attr_s { * Registered Port List */ struct fdmi_port_list_s { - __be32 num_ports; /* number Of Port Entries */ - wwn_t port_entry; /* one or more */ + __be32 num_ports; /* number Of Port Entries */ + wwn_t port_entry; /* one or more */ }; /* @@ -1888,7 +1580,7 @@ struct fdmi_port_attr_s { * FDMI Register HBA Attributes */ struct fdmi_rhba_s { - wwn_t hba_id; /* HBA Identifier */ + wwn_t hba_id; /* HBA Identifier */ struct fdmi_port_list_s port_list; /* Registered Port List */ struct fdmi_hba_attr_s hba_attr_blk; /* HBA attribute block */ }; @@ -1897,8 +1589,8 @@ struct fdmi_rhba_s { * FDMI Register Port */ struct fdmi_rprt_s { - wwn_t hba_id; /* HBA Identifier */ - wwn_t port_name; /* Port wwn */ + wwn_t hba_id; /* HBA Identifier */ + wwn_t port_name; /* Port wwn */ struct fdmi_port_attr_s port_attr_blk; /* Port Attr Block */ }; @@ -1906,7 +1598,7 @@ struct fdmi_rprt_s { * FDMI Register Port Attributes */ struct fdmi_rpa_s { - wwn_t port_name; /* port wwn */ + wwn_t port_name; /* port wwn */ struct fdmi_port_attr_s port_attr_blk; /* Port Attr Block */ }; diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c index a4989a02e494..9c410b21db6d 100644 --- a/drivers/scsi/bfa/bfa_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcpim.c @@ -2180,7 +2180,7 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim) else m->cmnd.iodir = FCP_IODIR_NONE; - m->cmnd.cdb = *(scsi_cdb_t *) cmnd->cmnd; + m->cmnd.cdb = *(struct scsi_cdb_s *) cmnd->cmnd; fcp_dl = scsi_bufflen(cmnd); m->cmnd.fcp_dl = cpu_to_be32(fcp_dl); diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index 431cf72f7426..c1f72c49196f 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -957,7 +957,7 @@ bfa_iocpf_sm_disabling_sync_entry(struct bfa_iocpf_s *iocpf) bfa_ioc_hw_sem_get(iocpf->ioc); } -/** +/* * IOC hb ack request is being removed. */ static void @@ -1020,8 +1020,7 @@ bfa_iocpf_sm_initfail_sync_entry(struct bfa_iocpf_s *iocpf) bfa_ioc_hw_sem_get(iocpf->ioc); } -/** - * @brief +/* * Hardware initialization failed. */ static void @@ -1103,12 +1102,12 @@ bfa_iocpf_sm_initfail(struct bfa_iocpf_s *iocpf, enum iocpf_event event) static void bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf_s *iocpf) { - /** + /* * Mark IOC as failed in hardware and stop firmware. */ bfa_ioc_lpu_stop(iocpf->ioc); - /** + /* * Flush any queued up mailbox requests. */ bfa_ioc_mbox_hbfail(iocpf->ioc); @@ -1366,12 +1365,6 @@ bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env) { struct bfi_ioc_image_hdr_s fwhdr, *drv_fwhdr; - /* - * If bios/efi boot (flash based) -- return true - */ - if (bfa_ioc_is_bios_optrom(ioc)) - return BFA_TRUE; - bfa_ioc_fwver_get(ioc, &fwhdr); drv_fwhdr = (struct bfi_ioc_image_hdr_s *) bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0); @@ -1422,22 +1415,6 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force) boot_type = BFI_BOOT_TYPE_NORMAL; boot_env = BFI_BOOT_LOADER_OS; - /* - * Flash based firmware boot BIOS env. - */ - if (bfa_ioc_is_bios_optrom(ioc)) { - boot_type = BFI_BOOT_TYPE_FLASH; - boot_env = BFI_BOOT_LOADER_BIOS; - } - - /* - * Flash based firmware boot UEFI env. - */ - if (bfa_ioc_is_uefi(ioc)) { - boot_type = BFI_BOOT_TYPE_FLASH; - boot_env = BFI_BOOT_LOADER_UEFI; - } - /* * check if firmware is valid */ @@ -1466,8 +1443,7 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force) * convergence, IOC will be in operational state when 2nd driver * is loaded. */ - if (ioc_fwstate == BFI_IOC_DISABLED || - (!bfa_ioc_is_bios_optrom(ioc) && ioc_fwstate == BFI_IOC_OP)) { + if (ioc_fwstate == BFI_IOC_DISABLED || ioc_fwstate == BFI_IOC_OP) { /* * When using MSI-X any pending firmware ready event should @@ -1842,7 +1818,7 @@ bfa_ioc_fail_notify(struct bfa_ioc_s *ioc) struct bfa_ioc_hbfail_notify_s *notify; struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad; - /** + /* * Notify driver and common modules registered for notification. */ ioc->cbfn->hbfail_cbfn(ioc->bfa); @@ -2279,7 +2255,7 @@ bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc) return BFA_TRUE; } -/** +/* * Reset IOC fwstate registers. */ void diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index 5d2f34290e9d..ec9cf08b0e7f 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h @@ -296,15 +296,6 @@ struct bfa_ioc_hwif_s { #define BFA_IOC_FLASH_OFFSET_IN_CHUNK(off) (off % BFI_FLASH_CHUNK_SZ_WORDS) #define BFA_IOC_FLASH_CHUNK_ADDR(chunkno) (chunkno * BFI_FLASH_CHUNK_SZ_WORDS) -#ifdef BFA_IOC_IS_UEFI -#define bfa_ioc_is_bios_optrom(__ioc) (0) -#define bfa_ioc_is_uefi(__ioc) BFA_IOC_IS_UEFI -#else -#define bfa_ioc_is_bios_optrom(__ioc) \ - (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(__ioc)) < BFA_IOC_FWIMG_MINSZ) -#define bfa_ioc_is_uefi(__ioc) (0) -#endif - /* * IOC mailbox interface */ diff --git a/drivers/scsi/bfa/bfa_ioc_cb.c b/drivers/scsi/bfa/bfa_ioc_cb.c index 788ecca5aa01..e4a0713185b6 100644 --- a/drivers/scsi/bfa/bfa_ioc_cb.c +++ b/drivers/scsi/bfa/bfa_ioc_cb.c @@ -61,7 +61,7 @@ bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc) ioc->ioc_hwif = &hwif_cb; } -/** +/* * Return true if firmware of current driver matches the running firmware. */ static bfa_boolean_t @@ -70,8 +70,7 @@ bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc) struct bfi_ioc_image_hdr_s fwhdr; uint32_t fwstate = readl(ioc->ioc_regs.ioc_fwstate); - if ((fwstate == BFI_IOC_UNINIT) || bfa_ioc_is_uefi(ioc) || - bfa_ioc_is_bios_optrom(ioc)) + if (fwstate == BFI_IOC_UNINIT) return BFA_TRUE; bfa_ioc_fwver_get(ioc, &fwhdr); @@ -211,7 +210,7 @@ bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc) writel(1, ioc->ioc_regs.ioc_sem_reg); } -/** +/* * Synchronized IOC failure processing routines */ static void @@ -236,7 +235,7 @@ bfa_ioc_cb_sync_complete(struct bfa_ioc_s *ioc) uint32_t fwstate, alt_fwstate; fwstate = readl(ioc->ioc_regs.ioc_fwstate); - /** + /* * At this point, this IOC is hoding the hw sem in the * start path (fwcheck) OR in the disable/enable path * OR to check if the other IOC has acknowledged failure. diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c index ccfecfca0745..008d129ddfcd 100644 --- a/drivers/scsi/bfa/bfa_ioc_ct.c +++ b/drivers/scsi/bfa/bfa_ioc_ct.c @@ -351,7 +351,7 @@ bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc) writel(1, ioc->ioc_regs.ioc_sem_reg); } -/** +/* * Synchronized IOC failure processing routines */ static void @@ -393,7 +393,7 @@ bfa_ioc_ct_sync_complete(struct bfa_ioc_s *ioc) if (sync_ackd == 0) return BFA_TRUE; - /** + /* * The check below is to see whether any other PCI fn * has reinitialized the ASIC (reset sync_ackd bits) * and failed again while this IOC was waiting for hw @@ -412,7 +412,7 @@ bfa_ioc_ct_sync_complete(struct bfa_ioc_s *ioc) return BFA_TRUE; } - /** + /* * If another PCI fn reinitialized and failed again while * this IOC was waiting for hw sem, the sync_ackd bit for * this IOC need to be set again to allow reinitialization. diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c index 6577d0d922f6..1d34921f88bf 100644 --- a/drivers/scsi/bfa/bfa_svc.c +++ b/drivers/scsi/bfa/bfa_svc.c @@ -1372,7 +1372,7 @@ bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event) } } -/** +/* * login complete */ static void @@ -1691,7 +1691,7 @@ bfa_lps_send_logout(struct bfa_lps_s *lps) bfa_reqq_produce(lps->bfa, lps->reqq); } -/** +/* * send n2n pid set request to firmware */ static void @@ -1930,7 +1930,7 @@ bfa_lps_get_base_pid(struct bfa_s *bfa) return BFA_LPS_FROM_TAG(mod, 0)->lp_pid; } -/** +/* * Set PID in case of n2n (which is assigned during PLOGI) */ void -- cgit v1.2.3-59-g8ed1b From 5c10007560589a2335a77cbc92347b1474518296 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 29 Dec 2010 15:57:54 +0100 Subject: [SCSI] gdth: Add missing call to gdth_ioctl_free Add missing call to gdth_ioctl_free before aborting. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression buf,ha,len,addr,E; @@ buf = gdth_ioctl_alloc(ha, len, FALSE, &addr) ... when != false buf != NULL when != true buf == NULL when != \(E = buf\|buf = E\) when != gdth_ioctl_free(ha, len, buf, addr) *return ...; // Signed-off-by: Julia Lawall Signed-off-by: James Bottomley --- drivers/scsi/gdth.c | 4 +++- drivers/scsi/gdth_proc.c | 16 ++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 76365700e2d5..3242bcabad97 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -4273,8 +4273,10 @@ static int ioc_general(void __user *arg, char *cmnd) } rval = __gdth_execute(ha->sdev, &gen.command, cmnd, gen.timeout, &gen.info); - if (rval < 0) + if (rval < 0) { + gdth_ioctl_free(ha, gen.data_len+gen.sense_len, buf, paddr); return rval; + } gen.status = rval; if (copy_to_user(arg + sizeof(gdth_ioctl_general), buf, diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c index 0572b9bf4bd6..652754319a4b 100644 --- a/drivers/scsi/gdth_proc.c +++ b/drivers/scsi/gdth_proc.c @@ -365,8 +365,10 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, len = 0; begin = pos; } - if (pos > offset + length) + if (pos > offset + length) { + gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr); goto stop_output; + } } } gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr); @@ -450,8 +452,10 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, len = 0; begin = pos; } - if (pos > offset + length) + if (pos > offset + length) { + gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr); goto stop_output; + } } while (drv_no != -1); if (is_mirr) { @@ -472,8 +476,10 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, len = 0; begin = pos; } - if (pos > offset + length) + if (pos > offset + length) { + gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr); goto stop_output; + } } gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr); @@ -542,8 +548,10 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, len = 0; begin = pos; } - if (pos > offset + length) + if (pos > offset + length) { + gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr); goto stop_output; + } } } gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr); -- cgit v1.2.3-59-g8ed1b From df4da5cdfca05b37b366b9c69925b68586969c1c Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Fri, 31 Dec 2010 02:22:18 -0600 Subject: [SCSI] libiscsi: add more informative failure message during iscsi scsi eh This adds a more informative error code and message for the iscsi scsi eh session drop paths. This allows you to distinguish if the session was dropped due to a connection failure vs the iscsi layer dropping the session due to scsi eh failure processing. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 10 +++++----- include/scsi/iscsi_if.h | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 7551abe40900..3eddab0774e4 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1796,9 +1796,9 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, NULL, 0); if (!task) { spin_unlock_bh(&session->lock); + iscsi_conn_printk(KERN_ERR, conn, "Could not send TMF.\n"); iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); spin_lock_bh(&session->lock); - ISCSI_DBG_EH(session, "tmf exec failure\n"); return -EPERM; } conn->tmfcmd_pdus_cnt++; @@ -2203,7 +2203,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) goto success_unlocked; case TMF_TIMEDOUT: spin_unlock_bh(&session->lock); - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST); goto failed_unlocked; case TMF_NOT_FOUND: if (!sc->SCp.ptr) { @@ -2290,7 +2290,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) break; case TMF_TIMEDOUT: spin_unlock_bh(&session->lock); - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST); goto done; default: conn->tmf_state = TMF_INITIAL; @@ -2371,7 +2371,7 @@ failed: * we drop the lock here but the leadconn cannot be destoyed while * we are in the scsi eh */ - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST); ISCSI_DBG_EH(session, "wait for relogin\n"); wait_event_interruptible(conn->ehwait, @@ -2453,7 +2453,7 @@ int iscsi_eh_target_reset(struct scsi_cmnd *sc) break; case TMF_TIMEDOUT: spin_unlock_bh(&session->lock); - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST); goto done; default: conn->tmf_state = TMF_INITIAL; diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index a8631acd37c3..c3e1cbcc2ad2 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h @@ -263,6 +263,7 @@ enum iscsi_err { ISCSI_ERR_INVALID_HOST = ISCSI_ERR_BASE + 18, ISCSI_ERR_XMIT_FAILED = ISCSI_ERR_BASE + 19, ISCSI_ERR_TCP_CONN_CLOSE = ISCSI_ERR_BASE + 20, + ISCSI_ERR_SCSI_EH_SESSION_RST = ISCSI_ERR_BASE + 21, }; /* -- cgit v1.2.3-59-g8ed1b From bc7accec8788ada4f459461194c2b8fad94ed239 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Fri, 31 Dec 2010 02:22:19 -0600 Subject: [SCSI] be2iscsi: fix gfp use in alloc_pdu The pdu allication callout is called from a spin lock and in the IO path so we cannot use GFP_KERNEL. This has the driver use GFP_ATOMIC. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 75a85aa9e882..be07ca06177e 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -3785,7 +3785,7 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode) dma_addr_t paddr; io_task->cmd_bhs = pci_pool_alloc(beiscsi_sess->bhs_pool, - GFP_KERNEL, &paddr); + GFP_ATOMIC, &paddr); if (!io_task->cmd_bhs) return -ENOMEM; io_task->bhs_pa.u.a64.address = paddr; -- cgit v1.2.3-59-g8ed1b From 1227633a441363642cdbaf38c4241d071e917095 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Fri, 31 Dec 2010 02:22:20 -0600 Subject: [SCSI] be2iscsi: fix null ptr when accessing task hdr If alloc_pdu fails then the task->hdr pointer may not be set. This adds a check for this case in the cleanup callback. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index be07ca06177e..79cefbe31367 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -3914,7 +3914,8 @@ static void beiscsi_cleanup_task(struct iscsi_task *task) io_task->psgl_handle = NULL; } } else { - if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN) + if (task->hdr && + ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN)) return; if (io_task->psgl_handle) { spin_lock(&phba->mgmt_sgl_lock); -- cgit v1.2.3-59-g8ed1b From f41d472179a0d7c8e8160c85180ab1124947068e Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Fri, 31 Dec 2010 02:22:21 -0600 Subject: [SCSI] libiscsi: do not take host lock in queuecommand iscsi_tcp, ib_iser, cxgb*, be2iscsi and bnx2i do not use the host lock and do not take the session lock against a irq, so this patch drops the DEF_SCSI_QCMD use. Instead we just take the session lock and disable bhs. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 37 ++++++++++++++----------------------- include/scsi/libiscsi.h | 3 ++- 2 files changed, 16 insertions(+), 24 deletions(-) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 3eddab0774e4..1def8e101249 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -505,6 +505,7 @@ static void iscsi_free_task(struct iscsi_task *task) struct iscsi_conn *conn = task->conn; struct iscsi_session *session = conn->session; struct scsi_cmnd *sc = task->sc; + int oldstate = task->state; ISCSI_DBG_SESSION(session, "freeing task itt 0x%x state %d sc %p\n", task->itt, task->state, task->sc); @@ -525,10 +526,10 @@ static void iscsi_free_task(struct iscsi_task *task) /* SCSI eh reuses commands to verify us */ sc->SCp.ptr = NULL; /* - * queue command may call this to free the task, but - * not have setup the sc callback + * queue command may call this to free the task, so + * it will decide how to return sc to scsi-ml. */ - if (sc->scsi_done) + if (oldstate != ISCSI_TASK_REQUEUE_SCSIQ) sc->scsi_done(sc); } } @@ -572,7 +573,8 @@ static void iscsi_complete_task(struct iscsi_task *task, int state) task->itt, task->state, task->sc); if (task->state == ISCSI_TASK_COMPLETED || task->state == ISCSI_TASK_ABRT_TMF || - task->state == ISCSI_TASK_ABRT_SESS_RECOV) + task->state == ISCSI_TASK_ABRT_SESS_RECOV || + task->state == ISCSI_TASK_REQUEUE_SCSIQ) return; WARN_ON_ONCE(task->state == ISCSI_TASK_FREE); task->state = state; @@ -1600,27 +1602,23 @@ enum { FAILURE_SESSION_NOT_READY, }; -static int iscsi_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) +int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc) { struct iscsi_cls_session *cls_session; - struct Scsi_Host *host; struct iscsi_host *ihost; int reason = 0; struct iscsi_session *session; struct iscsi_conn *conn; struct iscsi_task *task = NULL; - sc->scsi_done = done; sc->result = 0; sc->SCp.ptr = NULL; - host = sc->device->host; ihost = shost_priv(host); - spin_unlock(host->host_lock); cls_session = starget_to_session(scsi_target(sc->device)); session = cls_session->dd_data; - spin_lock(&session->lock); + spin_lock_bh(&session->lock); reason = iscsi_session_chkready(cls_session); if (reason) { @@ -1706,25 +1704,21 @@ static int iscsi_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi } session->queued_cmdsn++; - spin_unlock(&session->lock); - spin_lock(host->host_lock); + spin_unlock_bh(&session->lock); return 0; prepd_reject: - sc->scsi_done = NULL; - iscsi_complete_task(task, ISCSI_TASK_COMPLETED); + iscsi_complete_task(task, ISCSI_TASK_REQUEUE_SCSIQ); reject: - spin_unlock(&session->lock); + spin_unlock_bh(&session->lock); ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n", sc->cmnd[0], reason); - spin_lock(host->host_lock); return SCSI_MLQUEUE_TARGET_BUSY; prepd_fault: - sc->scsi_done = NULL; - iscsi_complete_task(task, ISCSI_TASK_COMPLETED); + iscsi_complete_task(task, ISCSI_TASK_REQUEUE_SCSIQ); fault: - spin_unlock(&session->lock); + spin_unlock_bh(&session->lock); ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n", sc->cmnd[0], reason); if (!scsi_bidi_cmnd(sc)) @@ -1733,12 +1727,9 @@ fault: scsi_out(sc)->resid = scsi_out(sc)->length; scsi_in(sc)->resid = scsi_in(sc)->length; } - done(sc); - spin_lock(host->host_lock); + sc->scsi_done(sc); return 0; } - -DEF_SCSI_QCMD(iscsi_queuecommand) EXPORT_SYMBOL_GPL(iscsi_queuecommand); int iscsi_change_queue_depth(struct scsi_device *sdev, int depth, int reason) diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 68e951d79f0b..748382b32b52 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -89,6 +89,7 @@ enum { ISCSI_TASK_RUNNING, ISCSI_TASK_ABRT_TMF, /* aborted due to TMF */ ISCSI_TASK_ABRT_SESS_RECOV, /* aborted due to session recovery */ + ISCSI_TASK_REQUEUE_SCSIQ, /* qcmd requeueing to scsi-ml */ }; struct iscsi_r2t_info { @@ -341,7 +342,7 @@ extern int iscsi_eh_abort(struct scsi_cmnd *sc); extern int iscsi_eh_recover_target(struct scsi_cmnd *sc); extern int iscsi_eh_session_reset(struct scsi_cmnd *sc); extern int iscsi_eh_device_reset(struct scsi_cmnd *sc); -extern int iscsi_queuecommand(struct Scsi_Host *h, struct scsi_cmnd *sc); +extern int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc); /* * iSCSI host helpers. -- cgit v1.2.3-59-g8ed1b From bfcf72e4426da2fd8f8081a641385ffc3ccc2282 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Fri, 31 Dec 2010 02:22:22 -0600 Subject: [SCSI] libiscsi: use bh locking instead of irq with session lock The session lock is taken in threads, timers, and bottom halves like softirqs and tasklets. All the code but iscsi_conn/session_failure take the session lock with the spin_lock_bh call. This was done because I thought some offload drivers would be calling these functions from a irq. They never did, so this patch has iscsi_conn/session_failure use the bh locking. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 1def8e101249..da8b61543ee4 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1338,17 +1338,16 @@ void iscsi_session_failure(struct iscsi_session *session, { struct iscsi_conn *conn; struct device *dev; - unsigned long flags; - spin_lock_irqsave(&session->lock, flags); + spin_lock_bh(&session->lock); conn = session->leadconn; if (session->state == ISCSI_STATE_TERMINATE || !conn) { - spin_unlock_irqrestore(&session->lock, flags); + spin_unlock_bh(&session->lock); return; } dev = get_device(&conn->cls_conn->dev); - spin_unlock_irqrestore(&session->lock, flags); + spin_unlock_bh(&session->lock); if (!dev) return; /* @@ -1367,17 +1366,16 @@ EXPORT_SYMBOL_GPL(iscsi_session_failure); void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err) { struct iscsi_session *session = conn->session; - unsigned long flags; - spin_lock_irqsave(&session->lock, flags); + spin_lock_bh(&session->lock); if (session->state == ISCSI_STATE_FAILED) { - spin_unlock_irqrestore(&session->lock, flags); + spin_unlock_bh(&session->lock); return; } if (conn->stop_stage == 0) session->state = ISCSI_STATE_FAILED; - spin_unlock_irqrestore(&session->lock, flags); + spin_unlock_bh(&session->lock); set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); -- cgit v1.2.3-59-g8ed1b From 41511704b678f7b101a76e58d6c6b7bbe2a9ad70 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 15 Nov 2010 16:04:56 -0500 Subject: [SCSI] eliminate an unnecessary local variable from scsi_remove_target() Signed-off-by: Alan Stern Signed-off-by: James Bottomley --- drivers/scsi/scsi_sysfs.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 76ee2e784f75..4c68d36f9ac2 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -993,16 +993,14 @@ static int __remove_child (struct device * dev, void * data) */ void scsi_remove_target(struct device *dev) { - struct device *rdev; - if (scsi_is_target_device(dev)) { __scsi_remove_target(to_scsi_target(dev)); return; } - rdev = get_device(dev); + get_device(dev); device_for_each_child(dev, NULL, __remove_child); - put_device(rdev); + put_device(dev); } EXPORT_SYMBOL(scsi_remove_target); -- cgit v1.2.3-59-g8ed1b From 474ffb74c75ea9845860ffb24cdc127eda0d5657 Mon Sep 17 00:00:00 2001 From: Tomas Henzl Date: Wed, 22 Dec 2010 16:52:40 +0100 Subject: [SCSI] lpfc: lower stack use in lpfc_fc_frame_check according to checkstack the lpfc_fc_frame_check occupies the first place in stack usage: make checkstack objdump -d vmlinux $(find . -name '*.ko') | \ perl /root/rpmbuild/BUILD/kernel-2.6.32/linux-2.6.32.x86_64/scripts/checkstack.pl x86_64 0x000013f4 lpfc_fc_frame_check [lpfc]: 1936 ... This change makes the rctl_names static, thus not on stack. Signed-off-by: Tomas Henzl Acked-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_sli.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index e98e792ab045..634b2fea9c4d 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -11578,7 +11578,8 @@ lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *phba, struct list_head *sblist, static int lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr) { - char *rctl_names[] = FC_RCTL_NAMES_INIT; + /* make rctl_names static to save stack space */ + static char *rctl_names[] = FC_RCTL_NAMES_INIT; char *type_names[] = FC_TYPE_NAMES_INIT; struct fc_vft_header *fc_vft_hdr; -- cgit v1.2.3-59-g8ed1b From c32e061fa19893ce4acf95d97d5613a161f0f1b7 Mon Sep 17 00:00:00 2001 From: roel kluin Date: Sat, 1 Jan 2011 19:40:23 +0100 Subject: [SCSI] arcmsr: fix write to device check Use command->sc_data_direction instead of trying (incorrectly) to figure it out from the command itself [jejb: fix up compile failure] Signed-off-by: Roel Kluin Acked-by: NickCheng Signed-off-by: James Bottomley --- drivers/scsi/arcmsr/arcmsr_hba.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 17e3df4f016f..1cadcd6b7da6 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -1171,9 +1171,8 @@ static int arcmsr_build_ccb(struct AdapterControlBlock *acb, arcmsr_cdb->msgPages = arccdbsize/0x100 + (arccdbsize % 0x100 ? 1 : 0); if ( arccdbsize > 256) arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE; - if (pcmd->cmnd[0]|WRITE_6 || pcmd->cmnd[0]|WRITE_10 || pcmd->cmnd[0]|WRITE_12 ){ + if (pcmd->sc_data_direction == DMA_TO_DEVICE) arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE; - } ccb->arc_cdb_size = arccdbsize; return SUCCESS; } -- cgit v1.2.3-59-g8ed1b