aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_init.c
diff options
context:
space:
mode:
authorAndrew Vasquez <andrew.vasquez@qlogic.com>2006-10-02 12:00:43 -0700
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-10-03 17:28:38 -0500
commitd8b4521349274ab610d0b29384c704444e55cbca (patch)
tree5af421c4c6c262e966e2e3f37241b1cdb4fa199a /drivers/scsi/qla2xxx/qla_init.c
parentee0ca6bab394fe41a2b4de58c4532b09a41c9165 (diff)
downloadkernel_samsung_espresso10-d8b4521349274ab610d0b29384c704444e55cbca.zip
kernel_samsung_espresso10-d8b4521349274ab610d0b29384c704444e55cbca.tar.gz
kernel_samsung_espresso10-d8b4521349274ab610d0b29384c704444e55cbca.tar.bz2
[SCSI] qla2xxx: Add iIDMA support.
iIDMA (Intelligent Interleaved Direct Memory Access) allows for the HBA hardware to send FC frames at the rate at which they can be received by a target device. By taking advantage of the higher link rate, the HBA can maximize bandwidth utilization in a heterogeneous multi-speed SAN. Within a fabric topology, port speed detection is done via a Name Server command (GFPN_ID) followed by a Fabric Management command (GPSC). In an FCAL/N2N topology, port speed is based on the HBA link-rate. Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_init.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c81
1 files changed, 81 insertions, 0 deletions
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 8596491..2700964 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -2074,6 +2074,19 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha)
new_fcport->flags &= ~FCF_FABRIC_DEVICE;
}
+ /* Base iIDMA settings on HBA port speed. */
+ switch (ha->link_data_rate) {
+ case PORT_SPEED_1GB:
+ fcport->fp_speed = cpu_to_be16(BIT_15);
+ break;
+ case PORT_SPEED_2GB:
+ fcport->fp_speed = cpu_to_be16(BIT_14);
+ break;
+ case PORT_SPEED_4GB:
+ fcport->fp_speed = cpu_to_be16(BIT_13);
+ break;
+ }
+
qla2x00_update_fcport(ha, fcport);
found_devs++;
@@ -2109,6 +2122,62 @@ qla2x00_probe_for_all_luns(scsi_qla_host_t *ha)
}
}
+static void
+qla2x00_iidma_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
+{
+#define LS_UNKNOWN 2
+ static char *link_speeds[5] = { "1", "2", "?", "4" };
+ int rval;
+ uint16_t port_speed, mb[6];
+
+ if (!IS_QLA24XX(ha))
+ return;
+
+ switch (be16_to_cpu(fcport->fp_speed)) {
+ case BIT_15:
+ port_speed = PORT_SPEED_1GB;
+ break;
+ case BIT_14:
+ port_speed = PORT_SPEED_2GB;
+ break;
+ case BIT_13:
+ port_speed = PORT_SPEED_4GB;
+ break;
+ default:
+ DEBUG2(printk("scsi(%ld): %02x%02x%02x%02x%02x%02x%02x%02x -- "
+ "unsupported FM port operating speed (%04x).\n",
+ ha->host_no, fcport->port_name[0], fcport->port_name[1],
+ fcport->port_name[2], fcport->port_name[3],
+ fcport->port_name[4], fcport->port_name[5],
+ fcport->port_name[6], fcport->port_name[7],
+ be16_to_cpu(fcport->fp_speed)));
+ port_speed = PORT_SPEED_UNKNOWN;
+ break;
+ }
+ if (port_speed == PORT_SPEED_UNKNOWN)
+ return;
+
+ rval = qla2x00_set_idma_speed(ha, fcport->loop_id, port_speed, mb);
+ if (rval != QLA_SUCCESS) {
+ DEBUG2(printk("scsi(%ld): Unable to adjust iIDMA "
+ "%02x%02x%02x%02x%02x%02x%02x%02x -- %04x %x %04x %04x.\n",
+ ha->host_no, fcport->port_name[0], fcport->port_name[1],
+ fcport->port_name[2], fcport->port_name[3],
+ fcport->port_name[4], fcport->port_name[5],
+ fcport->port_name[6], fcport->port_name[7], rval,
+ port_speed, mb[0], mb[1]));
+ } else {
+ DEBUG2(qla_printk(KERN_INFO, ha,
+ "iIDMA adjusted to %s GB/s on "
+ "%02x%02x%02x%02x%02x%02x%02x%02x.\n",
+ link_speeds[port_speed], fcport->port_name[0],
+ fcport->port_name[1], fcport->port_name[2],
+ fcport->port_name[3], fcport->port_name[4],
+ fcport->port_name[5], fcport->port_name[6],
+ fcport->port_name[7]));
+ }
+}
+
/*
* qla2x00_update_fcport
* Updates device on list.
@@ -2135,6 +2204,8 @@ qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
PORT_RETRY_TIME);
fcport->flags &= ~FCF_LOGIN_NEEDED;
+ qla2x00_iidma_fcport(ha, fcport);
+
atomic_set(&fcport->state, FCS_ONLINE);
if (ha->flags.init_done)
@@ -2416,6 +2487,8 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports)
} else if (qla2x00_gnn_id(ha, swl) != QLA_SUCCESS) {
kfree(swl);
swl = NULL;
+ } else if (qla2x00_gfpn_id(ha, swl) == QLA_SUCCESS) {
+ qla2x00_gpsc(ha, swl);
}
}
swl_idx = 0;
@@ -2450,6 +2523,9 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports)
swl[swl_idx].node_name, WWN_SIZE);
memcpy(new_fcport->port_name,
swl[swl_idx].port_name, WWN_SIZE);
+ memcpy(new_fcport->fabric_port_name,
+ swl[swl_idx].fabric_port_name, WWN_SIZE);
+ new_fcport->fp_speed = swl[swl_idx].fp_speed;
if (swl[swl_idx].d_id.b.rsvd_1 != 0) {
last_dev = 1;
@@ -2507,6 +2583,11 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports)
found++;
+ /* Update port state. */
+ memcpy(fcport->fabric_port_name,
+ new_fcport->fabric_port_name, WWN_SIZE);
+ fcport->fp_speed = new_fcport->fp_speed;
+
/*
* If address the same and state FCS_ONLINE, nothing
* changed.