diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-04 18:57:35 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-04 18:57:35 -0700 |
commit | 97d41e90fe61399b99d74820cb7f2d6e0fbac91d (patch) | |
tree | f759371424a26963b04badbb4433e360be4e8750 /drivers/scsi/qla2xxx | |
parent | 3bdc9d0b408e01c4e556daba0035ba37f603e920 (diff) | |
parent | afaf5a2d341d33b66b47c2716a263ce593460a08 (diff) | |
download | op-kernel-dev-97d41e90fe61399b99d74820cb7f2d6e0fbac91d.zip op-kernel-dev-97d41e90fe61399b99d74820cb7f2d6e0fbac91d.tar.gz |
Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (54 commits)
[SCSI] Initial Commit of qla4xxx
[SCSI] raid class: handle component-add errors
[SCSI] SCSI megaraid_sas: handle thrown errors
[SCSI] SCSI aic94xx: handle sysfs errors
[SCSI] SCSI st: fix error handling in module init, sysfs
[SCSI] SCSI sd: fix module init/exit error handling
[SCSI] SCSI osst: add error handling to module init, sysfs
[SCSI] scsi: remove hosts.h
[SCSI] scsi: Scsi_Cmnd convertion in aic7xxx_old.c
[SCSI] megaraid_sas: sets ioctl timeout and updates version,changelog
[SCSI] megaraid_sas: adds tasklet for cmd completion
[SCSI] megaraid_sas: prints pending cmds before setting hw_crit_error
[SCSI] megaraid_sas: function pointer for disable interrupt
[SCSI] megaraid_sas: frame count optimization
[SCSI] megaraid_sas: FW transition and q size changes
[SCSI] qla2xxx: Update version number to 8.01.07-k2.
[SCSI] qla2xxx: Stall mid-layer error handlers while rport is blocked.
[SCSI] qla2xxx: Add MODULE_FIRMWARE tags.
[SCSI] qla2xxx: Add support for host port state FC transport attribute.
[SCSI] qla2xxx: Add support for fabric name FC transport attribute.
...
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 57 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 40 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 9 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gs.c | 228 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 84 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 4 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 86 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 48 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_version.h | 2 |
9 files changed, 524 insertions, 34 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 87f90c4..ee75a71 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -691,13 +691,13 @@ qla2x00_get_host_speed(struct Scsi_Host *shost) uint32_t speed = 0; switch (ha->link_data_rate) { - case LDR_1GB: + case PORT_SPEED_1GB: speed = 1; break; - case LDR_2GB: + case PORT_SPEED_2GB: speed = 2; break; - case LDR_4GB: + case PORT_SPEED_4GB: speed = 4; break; } @@ -849,6 +849,49 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) return pfc_host_stat; } +static void +qla2x00_get_host_symbolic_name(struct Scsi_Host *shost) +{ + scsi_qla_host_t *ha = to_qla_host(shost); + + qla2x00_get_sym_node_name(ha, fc_host_symbolic_name(shost)); +} + +static void +qla2x00_set_host_system_hostname(struct Scsi_Host *shost) +{ + scsi_qla_host_t *ha = to_qla_host(shost); + + set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags); +} + +static void +qla2x00_get_host_fabric_name(struct Scsi_Host *shost) +{ + scsi_qla_host_t *ha = to_qla_host(shost); + u64 node_name; + + if (ha->device_flags & SWITCH_FOUND) + node_name = wwn_to_u64(ha->fabric_node_name); + else + node_name = wwn_to_u64(ha->node_name); + + fc_host_fabric_name(shost) = node_name; +} + +static void +qla2x00_get_host_port_state(struct Scsi_Host *shost) +{ + scsi_qla_host_t *ha = to_qla_host(shost); + + if (!ha->flags.online) + fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE; + else if (atomic_read(&ha->loop_state) == LOOP_TIMEOUT) + fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN; + else + fc_host_port_state(shost) = FC_PORTSTATE_ONLINE; +} + struct fc_function_template qla2xxx_transport_functions = { .show_host_node_name = 1, @@ -861,6 +904,14 @@ struct fc_function_template qla2xxx_transport_functions = { .show_host_speed = 1, .get_host_port_type = qla2x00_get_host_port_type, .show_host_port_type = 1, + .get_host_symbolic_name = qla2x00_get_host_symbolic_name, + .show_host_symbolic_name = 1, + .set_host_system_hostname = qla2x00_set_host_system_hostname, + .show_host_system_hostname = 1, + .get_host_fabric_name = qla2x00_get_host_fabric_name, + .show_host_fabric_name = 1, + .get_host_port_state = qla2x00_get_host_port_state, + .show_host_port_state = 1, .dd_fcrport_size = sizeof(struct fc_port *), .show_rport_supported_classes = 1, diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 0930260..c37a30a 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -608,6 +608,7 @@ typedef struct { */ #define MBC_SERDES_PARAMS 0x10 /* Serdes Tx Parameters. */ #define MBC_GET_IOCB_STATUS 0x12 /* Get IOCB status command. */ +#define MBC_PORT_PARAMS 0x1A /* Port iDMA Parameters. */ #define MBC_GET_TIMEOUT_PARAMS 0x22 /* Get FW timeouts. */ #define MBC_TRACE_CONTROL 0x27 /* Trace control command. */ #define MBC_GEN_SYSTEM_ERROR 0x2a /* Generate System Error. */ @@ -1497,6 +1498,9 @@ typedef struct { port_id_t d_id; uint8_t node_name[WWN_SIZE]; uint8_t port_name[WWN_SIZE]; + uint8_t fabric_port_name[WWN_SIZE]; + uint16_t fp_speeds; + uint16_t fp_speed; } sw_info_t; /* @@ -1524,6 +1528,9 @@ typedef struct fc_port { uint16_t loop_id; uint16_t old_loop_id; + uint8_t fabric_port_name[WWN_SIZE]; + uint16_t fp_speed; + fc_port_type_t port_type; atomic_t state; @@ -1635,6 +1642,15 @@ typedef struct fc_port { #define RSNN_NN_REQ_SIZE (16 + 8 + 1 + 255) #define RSNN_NN_RSP_SIZE 16 +#define GFPN_ID_CMD 0x11C +#define GFPN_ID_REQ_SIZE (16 + 4) +#define GFPN_ID_RSP_SIZE (16 + 8) + +#define GPSC_CMD 0x127 +#define GPSC_REQ_SIZE (16 + 8) +#define GPSC_RSP_SIZE (16 + 2 + 2) + + /* * HBA attribute types. */ @@ -1748,7 +1764,7 @@ struct ct_sns_req { uint8_t reserved[3]; union { - /* GA_NXT, GPN_ID, GNN_ID, GFT_ID */ + /* GA_NXT, GPN_ID, GNN_ID, GFT_ID, GFPN_ID */ struct { uint8_t reserved; uint8_t port_id[3]; @@ -1823,6 +1839,10 @@ struct ct_sns_req { struct { uint8_t port_name[8]; } dpa; + + struct { + uint8_t port_name[8]; + } gpsc; } req; }; @@ -1886,6 +1906,15 @@ struct ct_sns_rsp { uint8_t port_name[8]; struct ct_fdmi_hba_attributes attrs; } ghat; + + struct { + uint8_t port_name[8]; + } gfpn_id; + + struct { + uint16_t speeds; + uint16_t speed; + } gpsc; } rsp; }; @@ -2182,11 +2211,11 @@ typedef struct scsi_qla_host { uint16_t max_public_loop_ids; uint16_t min_external_loopid; /* First external loop Id */ +#define PORT_SPEED_UNKNOWN 0xFFFF +#define PORT_SPEED_1GB 0x00 +#define PORT_SPEED_2GB 0x01 +#define PORT_SPEED_4GB 0x03 uint16_t link_data_rate; /* F/W operating speed */ -#define LDR_1GB 0 -#define LDR_2GB 1 -#define LDR_4GB 3 -#define LDR_UNKNOWN 0xFFFF uint8_t current_topology; uint8_t prev_topology; @@ -2333,6 +2362,7 @@ typedef struct scsi_qla_host { uint8_t *node_name; uint8_t *port_name; + uint8_t fabric_node_name[WWN_SIZE]; uint32_t isp_abort_cnt; /* Option ROM information. */ diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 8311ac2..bef7011 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -208,6 +208,12 @@ qla2x00_trace_control(scsi_qla_host_t *, uint16_t, dma_addr_t, uint16_t); extern int qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t, uint16_t); +extern int +qla2x00_get_idma_speed(scsi_qla_host_t *, uint16_t, uint16_t *, uint16_t *); + +extern int +qla2x00_set_idma_speed(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t *); + /* * Global Function Prototypes in qla_isr.c source file. */ @@ -279,6 +285,9 @@ extern int qla2x00_rsnn_nn(scsi_qla_host_t *); extern void *qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t); extern void *qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *, uint32_t, uint32_t); extern int qla2x00_fdmi_register(scsi_qla_host_t *); +extern int qla2x00_gfpn_id(scsi_qla_host_t *, sw_info_t *); +extern int qla2x00_gpsc(scsi_qla_host_t *, sw_info_t *); +extern void qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *); /* * Global Function Prototypes in qla_attr.c source file. diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 2ebf259..97fbc62 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -612,6 +612,14 @@ qla2x00_rnn_id(scsi_qla_host_t *ha) return (rval); } +void +qla2x00_get_sym_node_name(scsi_qla_host_t *ha, uint8_t *snn) +{ + sprintf(snn, "%s FW:v%d.%02d.%02d DVR:v%s",ha->model_number, + ha->fw_major_version, ha->fw_minor_version, + ha->fw_subminor_version, qla2x00_version_str); +} + /** * qla2x00_rsnn_nn() - SNS Register Symbolic Node Name (RSNN_NN) of the HBA. * @ha: HA context @@ -622,9 +630,6 @@ int qla2x00_rsnn_nn(scsi_qla_host_t *ha) { int rval; - uint8_t *snn; - uint8_t version[20]; - ms_iocb_entry_t *ms_pkt; struct ct_sns_req *ct_req; struct ct_sns_rsp *ct_rsp; @@ -649,20 +654,11 @@ qla2x00_rsnn_nn(scsi_qla_host_t *ha) memcpy(ct_req->req.rsnn_nn.node_name, ha->node_name, WWN_SIZE); /* Prepare the Symbolic Node Name */ - /* Board type */ - snn = ct_req->req.rsnn_nn.sym_node_name; - strcpy(snn, ha->model_number); - /* Firmware version */ - strcat(snn, " FW:v"); - sprintf(version, "%d.%02d.%02d", ha->fw_major_version, - ha->fw_minor_version, ha->fw_subminor_version); - strcat(snn, version); - /* Driver version */ - strcat(snn, " DVR:v"); - strcat(snn, qla2x00_version_str); + qla2x00_get_sym_node_name(ha, ct_req->req.rsnn_nn.sym_node_name); /* Calculate SNN length */ - ct_req->req.rsnn_nn.name_len = (uint8_t)strlen(snn); + ct_req->req.rsnn_nn.name_len = + (uint8_t)strlen(ct_req->req.rsnn_nn.sym_node_name); /* Update MS IOCB request */ ms_pkt->req_bytecount = @@ -687,7 +683,6 @@ qla2x00_rsnn_nn(scsi_qla_host_t *ha) return (rval); } - /** * qla2x00_prep_sns_cmd() - Prepare common SNS command request fields for query. * @ha: HA context @@ -1585,6 +1580,21 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) DEBUG13(printk("%s(%ld): OS_DEVICE_NAME=%s.\n", __func__, ha->host_no, eiter->a.os_dev_name)); + /* Hostname. */ + if (strlen(fc_host_system_hostname(ha->host))) { + eiter = (struct ct_fdmi_port_attr *) (entries + size); + eiter->type = __constant_cpu_to_be16(FDMI_PORT_HOST_NAME); + snprintf(eiter->a.host_name, sizeof(eiter->a.host_name), + "%s", fc_host_system_hostname(ha->host)); + alen = strlen(eiter->a.host_name); + alen += (alen & 3) ? (4 - (alen & 3)) : 4; + eiter->len = cpu_to_be16(4 + alen); + size += 4 + alen; + + DEBUG13(printk("%s(%ld): HOSTNAME=%s.\n", __func__, + ha->host_no, eiter->a.host_name)); + } + /* Update MS request size. */ qla2x00_update_ms_fdmi_iocb(ha, size + 16); @@ -1647,3 +1657,189 @@ qla2x00_fdmi_register(scsi_qla_host_t *ha) return rval; } + +/** + * qla2x00_gfpn_id() - SNS Get Fabric Port Name (GFPN_ID) query. + * @ha: HA context + * @list: switch info entries to populate + * + * Returns 0 on success. + */ +int +qla2x00_gfpn_id(scsi_qla_host_t *ha, sw_info_t *list) +{ + int rval; + uint16_t i; + + ms_iocb_entry_t *ms_pkt; + struct ct_sns_req *ct_req; + struct ct_sns_rsp *ct_rsp; + + if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) + return QLA_FUNCTION_FAILED; + + for (i = 0; i < MAX_FIBRE_DEVICES; i++) { + /* Issue GFPN_ID */ + memset(list[i].fabric_port_name, 0, WWN_SIZE); + + /* Prepare common MS IOCB */ + ms_pkt = qla2x00_prep_ms_iocb(ha, GFPN_ID_REQ_SIZE, + GFPN_ID_RSP_SIZE); + + /* Prepare CT request */ + ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GFPN_ID_CMD, + GFPN_ID_RSP_SIZE); + ct_rsp = &ha->ct_sns->p.rsp; + + /* Prepare CT arguments -- port_id */ + ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain; + ct_req->req.port_id.port_id[1] = list[i].d_id.b.area; + ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa; + + /* Execute MS IOCB */ + rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma, + sizeof(ms_iocb_entry_t)); + if (rval != QLA_SUCCESS) { + /*EMPTY*/ + DEBUG2_3(printk("scsi(%ld): GFPN_ID issue IOCB " + "failed (%d).\n", ha->host_no, rval)); + } else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, + "GFPN_ID") != QLA_SUCCESS) { + rval = QLA_FUNCTION_FAILED; + } else { + /* Save fabric portname */ + memcpy(list[i].fabric_port_name, + ct_rsp->rsp.gfpn_id.port_name, WWN_SIZE); + } + + /* Last device exit. */ + if (list[i].d_id.b.rsvd_1 != 0) + break; + } + + return (rval); +} + +static inline void * +qla24xx_prep_ms_fm_iocb(scsi_qla_host_t *ha, uint32_t req_size, + uint32_t rsp_size) +{ + struct ct_entry_24xx *ct_pkt; + + ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb; + memset(ct_pkt, 0, sizeof(struct ct_entry_24xx)); + + ct_pkt->entry_type = CT_IOCB_TYPE; + ct_pkt->entry_count = 1; + ct_pkt->nport_handle = cpu_to_le16(ha->mgmt_svr_loop_id); + ct_pkt->timeout = __constant_cpu_to_le16(59); + ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1); + ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1); + ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size); + ct_pkt->cmd_byte_count = cpu_to_le32(req_size); + + ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); + ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); + ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count; + + ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); + ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); + ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count; + + return ct_pkt; +} + + +static inline struct ct_sns_req * +qla24xx_prep_ct_fm_req(struct ct_sns_req *ct_req, uint16_t cmd, + uint16_t rsp_size) +{ + memset(ct_req, 0, sizeof(struct ct_sns_pkt)); + + ct_req->header.revision = 0x01; + ct_req->header.gs_type = 0xFA; + ct_req->header.gs_subtype = 0x01; + ct_req->command = cpu_to_be16(cmd); + ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4); + + return ct_req; +} + +/** + * qla2x00_gpsc() - FCS Get Port Speed Capabilities (GPSC) query. + * @ha: HA context + * @list: switch info entries to populate + * + * Returns 0 on success. + */ +int +qla2x00_gpsc(scsi_qla_host_t *ha, sw_info_t *list) +{ + int rval; + uint16_t i; + + ms_iocb_entry_t *ms_pkt; + struct ct_sns_req *ct_req; + struct ct_sns_rsp *ct_rsp; + + if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) + return QLA_FUNCTION_FAILED; + + rval = qla2x00_mgmt_svr_login(ha); + if (rval) + return rval; + + for (i = 0; i < MAX_FIBRE_DEVICES; i++) { + /* Issue GFPN_ID */ + list[i].fp_speeds = list[i].fp_speed = 0; + + /* Prepare common MS IOCB */ + ms_pkt = qla24xx_prep_ms_fm_iocb(ha, GPSC_REQ_SIZE, + GPSC_RSP_SIZE); + + /* Prepare CT request */ + ct_req = qla24xx_prep_ct_fm_req(&ha->ct_sns->p.req, + GPSC_CMD, GPSC_RSP_SIZE); + ct_rsp = &ha->ct_sns->p.rsp; + + /* Prepare CT arguments -- port_name */ + memcpy(ct_req->req.gpsc.port_name, list[i].fabric_port_name, + WWN_SIZE); + + /* Execute MS IOCB */ + rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma, + sizeof(ms_iocb_entry_t)); + if (rval != QLA_SUCCESS) { + /*EMPTY*/ + DEBUG2_3(printk("scsi(%ld): GPSC issue IOCB " + "failed (%d).\n", ha->host_no, rval)); + } else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, + "GPSC") != QLA_SUCCESS) { + rval = QLA_FUNCTION_FAILED; + } else { + /* Save portname */ + list[i].fp_speeds = ct_rsp->rsp.gpsc.speeds; + list[i].fp_speed = ct_rsp->rsp.gpsc.speed; + + DEBUG2_3(printk("scsi(%ld): GPSC ext entry - " + "fpn %02x%02x%02x%02x%02x%02x%02x%02x speeds=%04x " + "speed=%04x.\n", ha->host_no, + list[i].fabric_port_name[0], + list[i].fabric_port_name[1], + list[i].fabric_port_name[2], + list[i].fabric_port_name[3], + list[i].fabric_port_name[4], + list[i].fabric_port_name[5], + list[i].fabric_port_name[6], + list[i].fabric_port_name[7], + be16_to_cpu(list[i].fp_speeds), + be16_to_cpu(list[i].fp_speed))); + } + + /* Last device exit. */ + if (list[i].d_id.b.rsvd_1 != 0) + break; + } + + return (rval); +} diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 8596491..d5d2627 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) @@ -2209,7 +2280,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) loop_id = NPH_F_PORT; else loop_id = SNS_FL_PORT; - rval = qla2x00_get_port_name(ha, loop_id, NULL, 0); + rval = qla2x00_get_port_name(ha, loop_id, ha->fabric_node_name, 1); if (rval != QLA_SUCCESS) { DEBUG2(printk("scsi(%ld): MBC_GET_PORT_NAME Failed, No FL " "Port\n", ha->host_no)); @@ -2217,6 +2288,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) ha->device_flags &= ~SWITCH_FOUND; return (QLA_SUCCESS); } + ha->device_flags |= SWITCH_FOUND; /* Mark devices that need re-synchronization. */ rval2 = qla2x00_device_resync(ha); @@ -2416,6 +2488,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 +2524,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 +2584,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. diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index de06131..5fa933c 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -400,7 +400,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) case MBA_LOOP_UP: /* Loop Up Event */ if (IS_QLA2100(ha) || IS_QLA2200(ha)) { link_speed = link_speeds[0]; - ha->link_data_rate = LDR_1GB; + ha->link_data_rate = PORT_SPEED_1GB; } else { link_speed = link_speeds[LS_UNKNOWN]; if (mb[1] < 5) @@ -429,7 +429,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) } ha->flags.management_server_logged_in = 0; - ha->link_data_rate = LDR_UNKNOWN; + ha->link_data_rate = PORT_SPEED_UNKNOWN; if (ql2xfdmienable) set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags); break; diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 879f281..4cde76c 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -2540,3 +2540,89 @@ qla2x00_read_sfp(scsi_qla_host_t *ha, dma_addr_t sfp_dma, uint16_t addr, return rval; } + +int +qla2x00_get_idma_speed(scsi_qla_host_t *ha, uint16_t loop_id, + uint16_t *port_speed, uint16_t *mb) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + if (!IS_QLA24XX(ha)) + return QLA_FUNCTION_FAILED; + + DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); + + mcp->mb[0] = MBC_PORT_PARAMS; + mcp->mb[1] = loop_id; + mcp->mb[2] = mcp->mb[3] = mcp->mb[4] = mcp->mb[5] = 0; + mcp->out_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_5|MBX_4|MBX_3|MBX_1|MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = qla2x00_mailbox_command(ha, mcp); + + /* Return mailbox statuses. */ + if (mb != NULL) { + mb[0] = mcp->mb[0]; + mb[1] = mcp->mb[1]; + mb[3] = mcp->mb[3]; + mb[4] = mcp->mb[4]; + mb[5] = mcp->mb[5]; + } + + if (rval != QLA_SUCCESS) { + DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__, + ha->host_no, rval)); + } else { + DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); + if (port_speed) + *port_speed = mcp->mb[3]; + } + + return rval; +} + +int +qla2x00_set_idma_speed(scsi_qla_host_t *ha, uint16_t loop_id, + uint16_t port_speed, uint16_t *mb) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + if (!IS_QLA24XX(ha)) + return QLA_FUNCTION_FAILED; + + DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); + + mcp->mb[0] = MBC_PORT_PARAMS; + mcp->mb[1] = loop_id; + mcp->mb[2] = BIT_0; + mcp->mb[3] = port_speed & (BIT_2|BIT_1|BIT_0); + mcp->mb[4] = mcp->mb[5] = 0; + mcp->out_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_5|MBX_4|MBX_3|MBX_1|MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = qla2x00_mailbox_command(ha, mcp); + + /* Return mailbox statuses. */ + if (mb != NULL) { + mb[0] = mcp->mb[0]; + mb[1] = mcp->mb[1]; + mb[3] = mcp->mb[3]; + mb[4] = mcp->mb[4]; + mb[5] = mcp->mb[5]; + } + + if (rval != QLA_SUCCESS) { + DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__, + ha->host_no, rval)); + } else { + DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); + } + + return rval; +} diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 65cbe2f..3ba8c23 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -589,6 +589,23 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha) return (return_status); } +static void +qla2x00_block_error_handler(struct scsi_cmnd *cmnd) +{ + struct Scsi_Host *shost = cmnd->device->host; + struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device)); + unsigned long flags; + + spin_lock_irqsave(shost->host_lock, flags); + while (rport->port_state == FC_PORTSTATE_BLOCKED) { + spin_unlock_irqrestore(shost->host_lock, flags); + msleep(1000); + spin_lock_irqsave(shost->host_lock, flags); + } + spin_unlock_irqrestore(shost->host_lock, flags); + return; +} + /************************************************************************** * qla2xxx_eh_abort * @@ -615,6 +632,8 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) unsigned long flags; int wait = 0; + qla2x00_block_error_handler(cmd); + if (!CMD_SP(cmd)) return SUCCESS; @@ -748,6 +767,8 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) unsigned int id, lun; unsigned long serial; + qla2x00_block_error_handler(cmd); + ret = FAILED; id = cmd->device->id; @@ -877,6 +898,8 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) unsigned int id, lun; unsigned long serial; + qla2x00_block_error_handler(cmd); + ret = FAILED; id = cmd->device->id; @@ -936,6 +959,8 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) unsigned int id, lun; unsigned long serial; + qla2x00_block_error_handler(cmd); + ret = FAILED; id = cmd->device->id; @@ -1385,7 +1410,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->prev_topology = 0; ha->init_cb_size = sizeof(init_cb_t); ha->mgmt_svr_loop_id = MANAGEMENT_SERVER; - ha->link_data_rate = LDR_UNKNOWN; + ha->link_data_rate = PORT_SPEED_UNKNOWN; ha->optrom_size = OPTROM_SIZE_2300; /* Assign ISP specific operations. */ @@ -2564,14 +2589,20 @@ qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout) #define FW_ISP2322 3 #define FW_ISP24XX 4 +#define FW_FILE_ISP21XX "ql2100_fw.bin" +#define FW_FILE_ISP22XX "ql2200_fw.bin" +#define FW_FILE_ISP2300 "ql2300_fw.bin" +#define FW_FILE_ISP2322 "ql2322_fw.bin" +#define FW_FILE_ISP24XX "ql2400_fw.bin" + static DECLARE_MUTEX(qla_fw_lock); static struct fw_blob qla_fw_blobs[FW_BLOBS] = { - { .name = "ql2100_fw.bin", .segs = { 0x1000, 0 }, }, - { .name = "ql2200_fw.bin", .segs = { 0x1000, 0 }, }, - { .name = "ql2300_fw.bin", .segs = { 0x800, 0 }, }, - { .name = "ql2322_fw.bin", .segs = { 0x800, 0x1c000, 0x1e000, 0 }, }, - { .name = "ql2400_fw.bin", }, + { .name = FW_FILE_ISP21XX, .segs = { 0x1000, 0 }, }, + { .name = FW_FILE_ISP22XX, .segs = { 0x1000, 0 }, }, + { .name = FW_FILE_ISP2300, .segs = { 0x800, 0 }, }, + { .name = FW_FILE_ISP2322, .segs = { 0x800, 0x1c000, 0x1e000, 0 }, }, + { .name = FW_FILE_ISP24XX, }, }; struct fw_blob * @@ -2702,3 +2733,8 @@ MODULE_AUTHOR("QLogic Corporation"); MODULE_DESCRIPTION("QLogic Fibre Channel HBA Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(QLA2XXX_VERSION); +MODULE_FIRMWARE(FW_FILE_ISP21XX); +MODULE_FIRMWARE(FW_FILE_ISP22XX); +MODULE_FIRMWARE(FW_FILE_ISP2300); +MODULE_FIRMWARE(FW_FILE_ISP2322); +MODULE_FIRMWARE(FW_FILE_ISP24XX); diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 9712590..e57bf45 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.01.07-k1" +#define QLA2XXX_VERSION "8.01.07-k2" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 1 |