Commit 4d4df193 authored by Harihara Kadayam's avatar Harihara Kadayam Committed by James Bottomley

[SCSI] qla2xxx: Add ISP84XX support.

Signed-off-by: default avatarRavi Anand <ravi.anand@qlogic.com>
Additional cleanups and
Signed-off-by: default avatarAndrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent b93480e3
...@@ -1291,7 +1291,7 @@ qla2x00_init_host_attr(scsi_qla_host_t *ha) ...@@ -1291,7 +1291,7 @@ qla2x00_init_host_attr(scsi_qla_host_t *ha)
if (IS_QLA25XX(ha)) if (IS_QLA25XX(ha))
speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT | speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT |
FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT; FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT;
else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) else if (IS_QLA24XX_TYPE(ha))
speed = FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT | speed = FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT |
FC_PORTSPEED_1GBIT; FC_PORTSPEED_1GBIT;
else if (IS_QLA23XX(ha)) else if (IS_QLA23XX(ha))
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
/* #define QL_DEBUG_LEVEL_13 */ /* Output fdmi function trace msgs */ /* #define QL_DEBUG_LEVEL_13 */ /* Output fdmi function trace msgs */
/* #define QL_DEBUG_LEVEL_14 */ /* Output RSCN trace msgs */ /* #define QL_DEBUG_LEVEL_14 */ /* Output RSCN trace msgs */
/* #define QL_DEBUG_LEVEL_15 */ /* Output NPIV trace msgs */ /* #define QL_DEBUG_LEVEL_15 */ /* Output NPIV trace msgs */
/* #define QL_DEBUG_LEVEL_16 */ /* Output ISP84XX trace msgs */
/* /*
* Macros use for debugging the driver. * Macros use for debugging the driver.
...@@ -41,6 +42,7 @@ ...@@ -41,6 +42,7 @@
#define DEBUG2_9_10(x) do { if (ql2xextended_error_logging) { x; } } while (0) #define DEBUG2_9_10(x) do { if (ql2xextended_error_logging) { x; } } while (0)
#define DEBUG2_11(x) do { if (ql2xextended_error_logging) { x; } } while (0) #define DEBUG2_11(x) do { if (ql2xextended_error_logging) { x; } } while (0)
#define DEBUG2_13(x) do { if (ql2xextended_error_logging) { x; } } while (0) #define DEBUG2_13(x) do { if (ql2xextended_error_logging) { x; } } while (0)
#define DEBUG2_16(x) do { if (ql2xextended_error_logging) { x; } } while (0)
#if defined(QL_DEBUG_LEVEL_3) #if defined(QL_DEBUG_LEVEL_3)
#define DEBUG3(x) do {x;} while (0) #define DEBUG3(x) do {x;} while (0)
...@@ -120,6 +122,12 @@ ...@@ -120,6 +122,12 @@
#define DEBUG15(x) do {} while (0) #define DEBUG15(x) do {} while (0)
#endif #endif
#if defined(QL_DEBUG_LEVEL_16)
#define DEBUG16(x) do {x;} while (0)
#else
#define DEBUG16(x) do {} while (0)
#endif
/* /*
* Firmware Dump structure definition * Firmware Dump structure definition
*/ */
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/aer.h> #include <linux/aer.h>
#include <linux/mutex.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include <scsi/scsi.h> #include <scsi/scsi.h>
...@@ -2142,6 +2143,21 @@ struct qla_work_evt { ...@@ -2142,6 +2143,21 @@ struct qla_work_evt {
} u; } u;
}; };
struct qla_chip_state_84xx {
struct list_head list;
struct kref kref;
void *bus;
spinlock_t access_lock;
struct mutex fw_update_mutex;
uint32_t fw_update;
uint32_t op_fw_version;
uint32_t op_fw_size;
uint32_t op_fw_seq_size;
uint32_t diag_fw_version;
uint32_t gold_fw_version;
};
/* /*
* Linux Host Adapter structure * Linux Host Adapter structure
*/ */
...@@ -2230,6 +2246,7 @@ typedef struct scsi_qla_host { ...@@ -2230,6 +2246,7 @@ typedef struct scsi_qla_host {
#define DFLG_NO_CABLE BIT_4 #define DFLG_NO_CABLE BIT_4
#define PCI_DEVICE_ID_QLOGIC_ISP2532 0x2532 #define PCI_DEVICE_ID_QLOGIC_ISP2532 0x2532
#define PCI_DEVICE_ID_QLOGIC_ISP8432 0x8432
uint32_t device_type; uint32_t device_type;
#define DT_ISP2100 BIT_0 #define DT_ISP2100 BIT_0
#define DT_ISP2200 BIT_1 #define DT_ISP2200 BIT_1
...@@ -2243,7 +2260,8 @@ typedef struct scsi_qla_host { ...@@ -2243,7 +2260,8 @@ typedef struct scsi_qla_host {
#define DT_ISP5422 BIT_9 #define DT_ISP5422 BIT_9
#define DT_ISP5432 BIT_10 #define DT_ISP5432 BIT_10
#define DT_ISP2532 BIT_11 #define DT_ISP2532 BIT_11
#define DT_ISP_LAST (DT_ISP2532 << 1) #define DT_ISP8432 BIT_12
#define DT_ISP_LAST (DT_ISP8432 << 1)
#define DT_IIDMA BIT_26 #define DT_IIDMA BIT_26
#define DT_FWI2 BIT_27 #define DT_FWI2 BIT_27
...@@ -2265,12 +2283,16 @@ typedef struct scsi_qla_host { ...@@ -2265,12 +2283,16 @@ typedef struct scsi_qla_host {
#define IS_QLA5422(ha) (DT_MASK(ha) & DT_ISP5422) #define IS_QLA5422(ha) (DT_MASK(ha) & DT_ISP5422)
#define IS_QLA5432(ha) (DT_MASK(ha) & DT_ISP5432) #define IS_QLA5432(ha) (DT_MASK(ha) & DT_ISP5432)
#define IS_QLA2532(ha) (DT_MASK(ha) & DT_ISP2532) #define IS_QLA2532(ha) (DT_MASK(ha) & DT_ISP2532)
#define IS_QLA8432(ha) (DT_MASK(ha) & DT_ISP8432)
#define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \ #define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \
IS_QLA6312(ha) || IS_QLA6322(ha)) IS_QLA6312(ha) || IS_QLA6322(ha))
#define IS_QLA24XX(ha) (IS_QLA2422(ha) || IS_QLA2432(ha)) #define IS_QLA24XX(ha) (IS_QLA2422(ha) || IS_QLA2432(ha))
#define IS_QLA54XX(ha) (IS_QLA5422(ha) || IS_QLA5432(ha)) #define IS_QLA54XX(ha) (IS_QLA5422(ha) || IS_QLA5432(ha))
#define IS_QLA25XX(ha) (IS_QLA2532(ha)) #define IS_QLA25XX(ha) (IS_QLA2532(ha))
#define IS_QLA84XX(ha) (IS_QLA8432(ha))
#define IS_QLA24XX_TYPE(ha) (IS_QLA24XX(ha) || IS_QLA54XX(ha) || \
IS_QLA84XX(ha))
#define IS_IIDMA_CAPABLE(ha) ((ha)->device_type & DT_IIDMA) #define IS_IIDMA_CAPABLE(ha) ((ha)->device_type & DT_IIDMA)
#define IS_FWI2_CAPABLE(ha) ((ha)->device_type & DT_FWI2) #define IS_FWI2_CAPABLE(ha) ((ha)->device_type & DT_FWI2)
...@@ -2575,6 +2597,8 @@ typedef struct scsi_qla_host { ...@@ -2575,6 +2597,8 @@ typedef struct scsi_qla_host {
#define VP_ERR_ADAP_NORESOURCES 5 #define VP_ERR_ADAP_NORESOURCES 5
uint16_t max_npiv_vports; /* 63 or 125 per topoloty */ uint16_t max_npiv_vports; /* 63 or 125 per topoloty */
int cur_vport_count; int cur_vport_count;
struct qla_chip_state_84xx *cs84xx;
} scsi_qla_host_t; } scsi_qla_host_t;
......
...@@ -1218,4 +1218,127 @@ struct qla_fdt_layout { ...@@ -1218,4 +1218,127 @@ struct qla_fdt_layout {
uint8_t protect_sec_cmd; uint8_t protect_sec_cmd;
uint8_t unused2[65]; uint8_t unused2[65];
}; };
/* 84XX Support **************************************************************/
#define MBA_ISP84XX_ALERT 0x800f /* Alert Notification. */
#define A84_PANIC_RECOVERY 0x1
#define A84_OP_LOGIN_COMPLETE 0x2
#define A84_DIAG_LOGIN_COMPLETE 0x3
#define A84_GOLD_LOGIN_COMPLETE 0x4
#define MBC_ISP84XX_RESET 0x3a /* Reset. */
#define FSTATE_REMOTE_FC_DOWN BIT_0
#define FSTATE_NSL_LINK_DOWN BIT_1
#define FSTATE_IS_DIAG_FW BIT_2
#define FSTATE_LOGGED_IN BIT_3
#define FSTATE_WAITING_FOR_VERIFY BIT_4
#define VERIFY_CHIP_IOCB_TYPE 0x1B
struct verify_chip_entry_84xx {
uint8_t entry_type;
uint8_t entry_count;
uint8_t sys_defined;
uint8_t entry_status;
uint32_t handle;
uint16_t options;
#define VCO_DONT_UPDATE_FW BIT_0
#define VCO_FORCE_UPDATE BIT_1
#define VCO_DONT_RESET_UPDATE BIT_2
#define VCO_DIAG_FW BIT_3
#define VCO_END_OF_DATA BIT_14
#define VCO_ENABLE_DSD BIT_15
uint16_t reserved_1;
uint16_t data_seg_cnt;
uint16_t reserved_2[3];
uint32_t fw_ver;
uint32_t exchange_address;
uint32_t reserved_3[3];
uint32_t fw_size;
uint32_t fw_seq_size;
uint32_t relative_offset;
uint32_t dseg_address[2];
uint32_t dseg_length;
};
struct verify_chip_rsp_84xx {
uint8_t entry_type;
uint8_t entry_count;
uint8_t sys_defined;
uint8_t entry_status;
uint32_t handle;
uint16_t comp_status;
#define CS_VCS_CHIP_FAILURE 0x3
#define CS_VCS_BAD_EXCHANGE 0x8
#define CS_VCS_SEQ_COMPLETEi 0x40
uint16_t failure_code;
#define VFC_CHECKSUM_ERROR 0x1
#define VFC_INVALID_LEN 0x2
#define VFC_ALREADY_IN_PROGRESS 0x8
uint16_t reserved_1[4];
uint32_t fw_ver;
uint32_t exchange_address;
uint32_t reserved_2[6];
};
#define ACCESS_CHIP_IOCB_TYPE 0x2B
struct access_chip_84xx {
uint8_t entry_type;
uint8_t entry_count;
uint8_t sys_defined;
uint8_t entry_status;
uint32_t handle;
uint16_t options;
#define ACO_DUMP_MEMORY 0x0
#define ACO_LOAD_MEMORY 0x1
#define ACO_CHANGE_CONFIG_PARAM 0x2
#define ACO_REQUEST_INFO 0x3
uint16_t reserved1;
uint16_t dseg_count;
uint16_t reserved2[3];
uint32_t parameter1;
uint32_t parameter2;
uint32_t parameter3;
uint32_t reserved3[3];
uint32_t total_byte_cnt;
uint32_t reserved4;
uint32_t dseg_address[2];
uint32_t dseg_length;
};
struct access_chip_rsp_84xx {
uint8_t entry_type;
uint8_t entry_count;
uint8_t sys_defined;
uint8_t entry_status;
uint32_t handle;
uint16_t comp_status;
uint16_t failure_code;
uint32_t residual_count;
uint32_t reserved[12];
};
#endif #endif
...@@ -47,6 +47,8 @@ extern void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *); ...@@ -47,6 +47,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_alloc_fw_dump(scsi_qla_host_t *);
extern void qla2x00_try_to_stop_firmware(scsi_qla_host_t *); extern void qla2x00_try_to_stop_firmware(scsi_qla_host_t *);
extern void qla84xx_put_chip(struct scsi_qla_host *);
/* /*
* Global Data in qla_os.c source file. * Global Data in qla_os.c source file.
*/ */
...@@ -149,6 +151,10 @@ qla2x00_verify_checksum(scsi_qla_host_t *, uint32_t); ...@@ -149,6 +151,10 @@ qla2x00_verify_checksum(scsi_qla_host_t *, uint32_t);
extern int extern int
qla2x00_issue_iocb(scsi_qla_host_t *, void *, dma_addr_t, size_t); qla2x00_issue_iocb(scsi_qla_host_t *, void *, dma_addr_t, size_t);
extern int
qla2x00_issue_iocb_timeout(scsi_qla_host_t *, void *, dma_addr_t, size_t,
uint32_t);
extern int extern int
qla2x00_abort_command(scsi_qla_host_t *, srb_t *); qla2x00_abort_command(scsi_qla_host_t *, srb_t *);
...@@ -249,6 +255,8 @@ qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t, uint16_t); ...@@ -249,6 +255,8 @@ qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t, uint16_t);
extern int extern int
qla2x00_set_idma_speed(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t *); qla2x00_set_idma_speed(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t *);
extern int qla84xx_verify_chip(struct scsi_qla_host *, uint16_t *);
/* /*
* Global Function Prototypes in qla_isr.c source file. * Global Function Prototypes in qla_isr.c source file.
*/ */
......
...@@ -1532,7 +1532,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) ...@@ -1532,7 +1532,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
eiter->a.sup_speed = __constant_cpu_to_be32( eiter->a.sup_speed = __constant_cpu_to_be32(
FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB| FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
FDMI_PORT_SPEED_4GB|FDMI_PORT_SPEED_8GB); FDMI_PORT_SPEED_4GB|FDMI_PORT_SPEED_8GB);
else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) else if (IS_QLA24XX_TYPE(ha))
eiter->a.sup_speed = __constant_cpu_to_be32( eiter->a.sup_speed = __constant_cpu_to_be32(
FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB| FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
FDMI_PORT_SPEED_4GB); FDMI_PORT_SPEED_4GB);
......
...@@ -37,6 +37,9 @@ static int qla2x00_restart_isp(scsi_qla_host_t *); ...@@ -37,6 +37,9 @@ static int qla2x00_restart_isp(scsi_qla_host_t *);
static int qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev); static int qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev);
static struct qla_chip_state_84xx *qla84xx_get_chip(struct scsi_qla_host *);
static int qla84xx_init_chip(scsi_qla_host_t *);
/****************************************************************************/ /****************************************************************************/
/* QLogic ISP2x00 Hardware Support Functions. */ /* QLogic ISP2x00 Hardware Support Functions. */
/****************************************************************************/ /****************************************************************************/
...@@ -108,6 +111,14 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) ...@@ -108,6 +111,14 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
return (rval); return (rval);
qla2xxx_get_flash_info(ha); qla2xxx_get_flash_info(ha);
} }
if (IS_QLA84XX(ha)) {
ha->cs84xx = qla84xx_get_chip(ha);
if (!ha->cs84xx) {
qla_printk(KERN_ERR, ha,
"Unable to configure ISP84XX.\n");
return QLA_FUNCTION_FAILED;
}
}
rval = qla2x00_init_rings(ha); rval = qla2x00_init_rings(ha);
return (rval); return (rval);
...@@ -1243,10 +1254,10 @@ static int ...@@ -1243,10 +1254,10 @@ static int
qla2x00_fw_ready(scsi_qla_host_t *ha) qla2x00_fw_ready(scsi_qla_host_t *ha)
{ {
int rval; int rval;
unsigned long wtime, mtime; unsigned long wtime, mtime, cs84xx_time;
uint16_t min_wait; /* Minimum wait time if loop is down */ uint16_t min_wait; /* Minimum wait time if loop is down */
uint16_t wait_time; /* Wait time if loop is coming ready */ uint16_t wait_time; /* Wait time if loop is coming ready */
uint16_t fw_state; uint16_t state[3];
rval = QLA_SUCCESS; rval = QLA_SUCCESS;
...@@ -1275,12 +1286,34 @@ qla2x00_fw_ready(scsi_qla_host_t *ha) ...@@ -1275,12 +1286,34 @@ qla2x00_fw_ready(scsi_qla_host_t *ha)
ha->host_no)); ha->host_no));
do { do {
rval = qla2x00_get_firmware_state(ha, &fw_state); rval = qla2x00_get_firmware_state(ha, state);
if (rval == QLA_SUCCESS) { if (rval == QLA_SUCCESS) {
if (fw_state < FSTATE_LOSS_OF_SYNC) { if (state[0] < FSTATE_LOSS_OF_SYNC) {
ha->device_flags &= ~DFLG_NO_CABLE; ha->device_flags &= ~DFLG_NO_CABLE;
} }
if (fw_state == FSTATE_READY) { if (IS_QLA84XX(ha) && state[0] != FSTATE_READY) {
DEBUG16(printk("scsi(%ld): fw_state=%x "
"84xx=%x.\n", ha->host_no, state[0],
state[2]));
if ((state[2] & FSTATE_LOGGED_IN) &&
(state[2] & FSTATE_WAITING_FOR_VERIFY)) {
DEBUG16(printk("scsi(%ld): Sending "
"verify iocb.\n", ha->host_no));
cs84xx_time = jiffies;
rval = qla84xx_init_chip(ha);
if (rval != QLA_SUCCESS)
break;
/* Add time taken to initialize. */
cs84xx_time = jiffies - cs84xx_time;
wtime += cs84xx_time;
mtime += cs84xx_time;
DEBUG16(printk("scsi(%ld): Increasing "
"wait time by %ld. New time %ld\n",
ha->host_no, cs84xx_time, wtime));
}
} else if (state[0] == FSTATE_READY) {
DEBUG(printk("scsi(%ld): F/W Ready - OK \n", DEBUG(printk("scsi(%ld): F/W Ready - OK \n",
ha->host_no)); ha->host_no));
...@@ -1294,7 +1327,7 @@ qla2x00_fw_ready(scsi_qla_host_t *ha) ...@@ -1294,7 +1327,7 @@ qla2x00_fw_ready(scsi_qla_host_t *ha)
rval = QLA_FUNCTION_FAILED; rval = QLA_FUNCTION_FAILED;
if (atomic_read(&ha->loop_down_timer) && if (atomic_read(&ha->loop_down_timer) &&
fw_state != FSTATE_READY) { state[0] != FSTATE_READY) {
/* Loop down. Timeout on min_wait for states /* Loop down. Timeout on min_wait for states
* other than Wait for Login. * other than Wait for Login.
*/ */
...@@ -1319,11 +1352,11 @@ qla2x00_fw_ready(scsi_qla_host_t *ha) ...@@ -1319,11 +1352,11 @@ qla2x00_fw_ready(scsi_qla_host_t *ha)
msleep(500); msleep(500);
DEBUG3(printk("scsi(%ld): fw_state=%x curr time=%lx.\n", DEBUG3(printk("scsi(%ld): fw_state=%x curr time=%lx.\n",
ha->host_no, fw_state, jiffies)); ha->host_no, state[0], jiffies));
} while (1); } while (1);
DEBUG(printk("scsi(%ld): fw_state=%x curr time=%lx.\n", DEBUG(printk("scsi(%ld): fw_state=%x curr time=%lx.\n",
ha->host_no, fw_state, jiffies)); ha->host_no, state[0], jiffies));
if (rval) { if (rval) {
DEBUG2_3(printk("scsi(%ld): Firmware ready **** FAILED ****.\n", DEBUG2_3(printk("scsi(%ld): Firmware ready **** FAILED ****.\n",
...@@ -4038,3 +4071,73 @@ qla24xx_configure_vhba(scsi_qla_host_t *ha) ...@@ -4038,3 +4071,73 @@ qla24xx_configure_vhba(scsi_qla_host_t *ha)
return rval; return rval;
} }
/* 84XX Support **************************************************************/
static LIST_HEAD(qla_cs84xx_list);
static DEFINE_MUTEX(qla_cs84xx_mutex);
static struct qla_chip_state_84xx *
qla84xx_get_chip(struct scsi_qla_host *ha)
{
struct qla_chip_state_84xx *cs84xx;
mutex_lock(&qla_cs84xx_mutex);
/* Find any shared 84xx chip. */
list_for_each_entry(cs84xx, &qla_cs84xx_list, list) {
if (cs84xx->bus == ha->pdev->bus) {
kref_get(&cs84xx->kref);
goto done;
}
}
cs84xx = kzalloc(sizeof(*cs84xx), GFP_KERNEL);
if (!cs84xx)
goto done;
kref_init(&cs84xx->kref);
spin_lock_init(&cs84xx->access_lock);
mutex_init(&cs84xx->fw_update_mutex);
cs84xx->bus = ha->pdev->bus;
list_add_tail(&cs84xx->list, &qla_cs84xx_list);
done:
mutex_unlock(&qla_cs84xx_mutex);
return cs84xx;
}
static void
__qla84xx_chip_release(struct kref *kref)
{
struct qla_chip_state_84xx *cs84xx =
container_of(kref, struct qla_chip_state_84xx, kref);
mutex_lock(&qla_cs84xx_mutex);
list_del(&cs84xx->list);
mutex_unlock(&qla_cs84xx_mutex);
kfree(cs84xx);
}
void
qla84xx_put_chip(struct scsi_qla_host *ha)
{
if (ha->cs84xx)
kref_put(&ha->cs84xx->kref, __qla84xx_chip_release);
}
static int
qla84xx_init_chip(scsi_qla_host_t *ha)
{
int rval;
uint16_t status[2];
mutex_lock(&ha->cs84xx->fw_update_mutex);
rval = qla84xx_verify_chip(ha, status);
mutex_unlock(&ha->cs84xx->fw_update_mutex);
return rval != QLA_SUCCESS || status[0] ? QLA_FUNCTION_FAILED:
QLA_SUCCESS;
}
...@@ -271,6 +271,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) ...@@ -271,6 +271,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
uint32_t rscn_entry, host_pid; uint32_t rscn_entry, host_pid;
uint8_t rscn_queue_index; uint8_t rscn_queue_index;
unsigned long flags;
/* Setup to process RIO completion. */ /* Setup to process RIO completion. */
handle_cnt = 0; handle_cnt = 0;
...@@ -432,9 +433,10 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) ...@@ -432,9 +433,10 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
break; break;
case MBA_LOOP_DOWN: /* Loop Down Event */ case MBA_LOOP_DOWN: /* Loop Down Event */
DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN (%x).\n", DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN "
ha->host_no, mb[1])); "(%x %x %x).\n", ha->host_no, mb[1], mb[2], mb[3]));
qla_printk(KERN_INFO, ha, "LOOP DOWN detected (%x).\n", mb[1]); qla_printk(KERN_INFO, ha, "LOOP DOWN detected (%x %x %x).\n",
mb[1], mb[2], mb[3]);
if (atomic_read(&ha->loop_state) != LOOP_DOWN) { if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
atomic_set(&ha->loop_state, LOOP_DOWN); atomic_set(&ha->loop_state, LOOP_DOWN);
...@@ -640,6 +642,42 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) ...@@ -640,6 +642,42 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
DEBUG2(printk("scsi(%ld): Trace Notification -- %04x %04x.\n", DEBUG2(printk("scsi(%ld): Trace Notification -- %04x %04x.\n",
ha->host_no, mb[1], mb[2])); ha->host_no, mb[1], mb[2]));
break; break;
case MBA_ISP84XX_ALERT:
DEBUG2(printk("scsi(%ld): ISP84XX Alert Notification -- "
"%04x %04x %04x\n", ha->host_no, mb[1], mb[2], mb[3]));
spin_lock_irqsave(&ha->cs84xx->access_lock, flags);
switch (mb[1]) {
case A84_PANIC_RECOVERY:
qla_printk(KERN_INFO, ha, "Alert 84XX: panic recovery "
"%04x %04x\n", mb[2], mb[3]);
break;
case A84_OP_LOGIN_COMPLETE:
ha->cs84xx->op_fw_version = mb[3] << 16 | mb[2];
DEBUG2(qla_printk(KERN_INFO, ha, "Alert 84XX:"
"firmware version %x\n", ha->cs84xx->op_fw_version));
break;
case A84_DIAG_LOGIN_COMPLETE:
ha->cs84xx->diag_fw_version = mb[3] << 16 | mb[2];
DEBUG2(qla_printk(KERN_INFO, ha, "Alert 84XX:"
"diagnostic firmware version %x\n",
ha->cs84xx->diag_fw_version));
break;
case A84_GOLD_LOGIN_COMPLETE:
ha->cs84xx->diag_fw_version = mb[3] << 16 | mb[2];
ha->cs84xx->fw_update = 1;
DEBUG2(qla_printk(KERN_INFO, ha, "Alert 84XX: gold "
"firmware version %x\n",
ha->cs84xx->gold_fw_version));
break;
default:
qla_printk(KERN_ERR, ha,
"Alert 84xx: Invalid Alert %04x %04x %04x\n",
mb[1], mb[2], mb[3]);
}
spin_unlock_irqrestore(&ha->cs84xx->access_lock, flags);
break;
} }
if (!ha->parent && ha->num_vhosts) if (!ha->parent && ha->num_vhosts)
...@@ -1747,7 +1785,7 @@ qla2x00_request_irqs(scsi_qla_host_t *ha) ...@@ -1747,7 +1785,7 @@ qla2x00_request_irqs(scsi_qla_host_t *ha)
device_reg_t __iomem *reg = ha->iobase; device_reg_t __iomem *reg = ha->iobase;
/* If possible, enable MSI-X. */ /* If possible, enable MSI-X. */
if (!IS_QLA2432(ha) && !IS_QLA2532(ha)) if (!IS_QLA2432(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha))
goto skip_msix; goto skip_msix;
if (IS_QLA2432(ha) && (ha->chip_revision < QLA_MSIX_CHIP_REV_24XX || if (IS_QLA2432(ha) && (ha->chip_revision < QLA_MSIX_CHIP_REV_24XX ||
...@@ -1782,7 +1820,7 @@ qla2x00_request_irqs(scsi_qla_host_t *ha) ...@@ -1782,7 +1820,7 @@ qla2x00_request_irqs(scsi_qla_host_t *ha)
"MSI-X: Falling back-to INTa mode -- %d.\n", ret); "MSI-X: Falling back-to INTa mode -- %d.\n", ret);
skip_msix: skip_msix:
if (!IS_QLA24XX(ha) && !IS_QLA2532(ha)) if (!IS_QLA24XX(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha))
goto skip_msi; goto skip_msi;
ret = pci_enable_msi(ha->pdev); ret = pci_enable_msi(ha->pdev);
......
...@@ -682,8 +682,8 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr) ...@@ -682,8 +682,8 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr)
* Kernel context. * Kernel context.
*/ */
int int
qla2x00_issue_iocb(scsi_qla_host_t *ha, void* buffer, dma_addr_t phys_addr, qla2x00_issue_iocb_timeout(scsi_qla_host_t *ha, void *buffer,
size_t size) dma_addr_t phys_addr, size_t size, uint32_t tov)
{ {
int rval; int rval;
mbx_cmd_t mc; mbx_cmd_t mc;
...@@ -697,7 +697,7 @@ qla2x00_issue_iocb(scsi_qla_host_t *ha, void* buffer, dma_addr_t phys_addr, ...@@ -697,7 +697,7 @@ qla2x00_issue_iocb(scsi_qla_host_t *ha, void* buffer, dma_addr_t phys_addr,
mcp->mb[7] = LSW(MSD(phys_addr)); mcp->mb[7] = LSW(MSD(phys_addr));
mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_2|MBX_0; mcp->in_mb = MBX_2|MBX_0;
mcp->tov = MBX_TOV_SECONDS; mcp->tov = tov;
mcp->flags = 0; mcp->flags = 0;
rval = qla2x00_mailbox_command(ha, mcp); rval = qla2x00_mailbox_command(ha, mcp);
...@@ -718,6 +718,14 @@ qla2x00_issue_iocb(scsi_qla_host_t *ha, void* buffer, dma_addr_t phys_addr, ...@@ -718,6 +718,14 @@ qla2x00_issue_iocb(scsi_qla_host_t *ha, void* buffer, dma_addr_t phys_addr,
return rval; return rval;
} }
int
qla2x00_issue_iocb(scsi_qla_host_t *ha, void *buffer, dma_addr_t phys_addr,
size_t size)
{
return qla2x00_issue_iocb_timeout(ha, buffer, phys_addr, size,
MBX_TOV_SECONDS);
}
/* /*
* qla2x00_abort_command * qla2x00_abort_command
* Abort command aborts a specified IOCB. * Abort command aborts a specified IOCB.
...@@ -1208,7 +1216,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) ...@@ -1208,7 +1216,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt)
* Kernel context. * Kernel context.
*/ */
int int
qla2x00_get_firmware_state(scsi_qla_host_t *ha, uint16_t *dptr) qla2x00_get_firmware_state(scsi_qla_host_t *ha, uint16_t *states)
{ {
int rval; int rval;
mbx_cmd_t mc; mbx_cmd_t mc;
...@@ -1219,13 +1227,15 @@ qla2x00_get_firmware_state(scsi_qla_host_t *ha, uint16_t *dptr) ...@@ -1219,13 +1227,15 @@ qla2x00_get_firmware_state(scsi_qla_host_t *ha, uint16_t *dptr)
mcp->mb[0] = MBC_GET_FIRMWARE_STATE; mcp->mb[0] = MBC_GET_FIRMWARE_STATE;
mcp->out_mb = MBX_0; mcp->out_mb = MBX_0;
mcp->in_mb = MBX_2|MBX_1|MBX_0; mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
mcp->tov = MBX_TOV_SECONDS; mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0; mcp->flags = 0;
rval = qla2x00_mailbox_command(ha, mcp); rval = qla2x00_mailbox_command(ha, mcp);
/* Return firmware state. */ /* Return firmware states. */
*dptr = mcp->mb[1]; states[0] = mcp->mb[1];
states[1] = mcp->mb[2];
states[2] = mcp->mb[3];
if (rval != QLA_SUCCESS) { if (rval != QLA_SUCCESS) {
/*EMPTY*/ /*EMPTY*/
...@@ -2937,3 +2947,104 @@ qla2x00_dump_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t addr, ...@@ -2937,3 +2947,104 @@ qla2x00_dump_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t addr,
return rval; return rval;
} }
/* 84XX Support **************************************************************/
struct cs84xx_mgmt_cmd {
union {
struct verify_chip_entry_84xx req;
struct verify_chip_rsp_84xx rsp;
} p;
};
int
qla84xx_verify_chip(struct scsi_qla_host *ha, uint16_t *status)
{
int rval, retry;
struct cs84xx_mgmt_cmd *mn;
dma_addr_t mn_dma;
uint16_t options;
unsigned long flags;
DEBUG16(printk("%s(%ld): entered.\n", __func__, ha->host_no));
mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
if (mn == NULL) {
DEBUG2_3(printk("%s(%ld): failed to allocate Verify ISP84XX "
"IOCB.\n", __func__, ha->host_no));
return QLA_MEMORY_ALLOC_FAILED;
}
/* Force Update? */
options = ha->cs84xx->fw_update ? VCO_FORCE_UPDATE : 0;
/* Diagnostic firmware? */
/* options |= MENLO_DIAG_FW; */
/* We update the firmware with only one data sequence. */
options |= VCO_END_OF_DATA;
retry = 0;
do {
memset(mn, 0, sizeof(*mn));
mn->p.req.entry_type = VERIFY_CHIP_IOCB_TYPE;
mn->p.req.entry_count = 1;
mn->p.req.options = cpu_to_le16(options);
DEBUG16(printk("%s(%ld): Dump of Verify Request.\n", __func__,
ha->host_no));
DEBUG16(qla2x00_dump_buffer((uint8_t *)mn,
sizeof(*mn)));
rval = qla2x00_issue_iocb_timeout(ha, mn, mn_dma, 0, 120);
if (rval != QLA_SUCCESS) {
DEBUG2_16(printk("%s(%ld): failed to issue Verify "
"IOCB (%x).\n", __func__, ha->host_no, rval));
goto verify_done;
}
DEBUG16(printk("%s(%ld): Dump of Verify Response.\n", __func__,
ha->host_no));
DEBUG16(qla2x00_dump_buffer((uint8_t *)mn,
sizeof(*mn)));
status[0] = le16_to_cpu(mn->p.rsp.comp_status);
status[1] = status[0] == CS_VCS_CHIP_FAILURE ?
le16_to_cpu(mn->p.rsp.failure_code) : 0;
DEBUG2_16(printk("%s(%ld): cs=%x fc=%x\n", __func__,
ha->host_no, status[0], status[1]));
if (status[0] != CS_COMPLETE) {
rval = QLA_FUNCTION_FAILED;
if (!(options & VCO_DONT_UPDATE_FW)) {
DEBUG2_16(printk("%s(%ld): Firmware update "
"failed. Retrying without update "
"firmware.\n", __func__, ha->host_no));
options |= VCO_DONT_UPDATE_FW;
options &= ~VCO_FORCE_UPDATE;
retry = 1;
}
} else {
DEBUG2_16(printk("%s(%ld): firmware updated to %x.\n",
__func__, ha->host_no,
le32_to_cpu(mn->p.rsp.fw_ver)));
/* NOTE: we only update OP firmware. */
spin_lock_irqsave(&ha->cs84xx->access_lock, flags);
ha->cs84xx->op_fw_version =
le32_to_cpu(mn->p.rsp.fw_ver);
spin_unlock_irqrestore(&ha->cs84xx->access_lock,
flags);
}
} while (retry);
verify_done:
dma_pool_free(ha->s_dma_pool, mn, mn_dma);
if (rval != QLA_SUCCESS) {
DEBUG2_16(printk("%s(%ld): failed=%x.\n", __func__,
ha->host_no, rval));
} else {
DEBUG16(printk("%s(%ld): done.\n", __func__, ha->host_no));
}
return rval;
}
...@@ -339,6 +339,8 @@ qla24xx_fw_version_str(struct scsi_qla_host *ha, char *str) ...@@ -339,6 +339,8 @@ qla24xx_fw_version_str(struct scsi_qla_host *ha, char *str)
strcat(str, "[T10 CRC] "); strcat(str, "[T10 CRC] ");
if (ha->fw_attributes & BIT_5) if (ha->fw_attributes & BIT_5)
strcat(str, "[VI] "); strcat(str, "[VI] ");
if (ha->fw_attributes & BIT_10)
strcat(str, "[84XX] ");
if (ha->fw_attributes & BIT_13) if (ha->fw_attributes & BIT_13)
strcat(str, "[Experimental]"); strcat(str, "[Experimental]");
return str; return str;
...@@ -1378,6 +1380,13 @@ qla2x00_set_isp_flags(scsi_qla_host_t *ha) ...@@ -1378,6 +1380,13 @@ qla2x00_set_isp_flags(scsi_qla_host_t *ha)
ha->device_type |= DT_IIDMA; ha->device_type |= DT_IIDMA;
ha->fw_srisc_address = RISC_START_ADDRESS_2400; ha->fw_srisc_address = RISC_START_ADDRESS_2400;
break; break;
case PCI_DEVICE_ID_QLOGIC_ISP8432:
ha->device_type |= DT_ISP8432;
ha->device_type |= DT_ZIO_SUPPORTED;
ha->device_type |= DT_FWI2;
ha->device_type |= DT_IIDMA;
ha->fw_srisc_address = RISC_START_ADDRESS_2400;
break;
case PCI_DEVICE_ID_QLOGIC_ISP5422: case PCI_DEVICE_ID_QLOGIC_ISP5422:
ha->device_type |= DT_ISP5422; ha->device_type |= DT_ISP5422;
ha->device_type |= DT_FWI2; ha->device_type |= DT_FWI2;
...@@ -1501,6 +1510,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -1501,6 +1510,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
sht = &qla2x00_driver_template; sht = &qla2x00_driver_template;
if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 || if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 ||
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 || pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 ||
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8432 ||
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 || pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 ||
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432 || pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432 ||
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532) { pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532) {
...@@ -1591,7 +1601,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -1591,7 +1601,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
if (IS_QLA2322(ha) || IS_QLA6322(ha)) if (IS_QLA2322(ha) || IS_QLA6322(ha))
ha->optrom_size = OPTROM_SIZE_2322; ha->optrom_size = OPTROM_SIZE_2322;
ha->isp_ops = &qla2300_isp_ops; ha->isp_ops = &qla2300_isp_ops;
} else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { } else if (IS_QLA24XX_TYPE(ha)) {
host->max_id = MAX_TARGETS_2200; host->max_id = MAX_TARGETS_2200;
ha->mbx_count = MAILBOX_REGISTER_COUNT; ha->mbx_count = MAILBOX_REGISTER_COUNT;
ha->request_q_length = REQUEST_ENTRY_CNT_24XX; ha->request_q_length = REQUEST_ENTRY_CNT_24XX;
...@@ -1736,6 +1746,8 @@ qla2x00_remove_one(struct pci_dev *pdev) ...@@ -1736,6 +1746,8 @@ qla2x00_remove_one(struct pci_dev *pdev)
qla2x00_dfs_remove(ha); qla2x00_dfs_remove(ha);
qla84xx_put_chip(ha);
qla2x00_free_sysfs_attr(ha); qla2x00_free_sysfs_attr(ha);
fc_remove_host(ha->host); fc_remove_host(ha->host);
...@@ -2642,7 +2654,7 @@ qla2x00_request_firmware(scsi_qla_host_t *ha) ...@@ -2642,7 +2654,7 @@ qla2x00_request_firmware(scsi_qla_host_t *ha)
blob = &qla_fw_blobs[FW_ISP2300]; blob = &qla_fw_blobs[FW_ISP2300];
} else if (IS_QLA2322(ha) || IS_QLA6322(ha)) { } else if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
blob = &qla_fw_blobs[FW_ISP2322]; blob = &qla_fw_blobs[FW_ISP2322];
} else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { } else if (IS_QLA24XX_TYPE(ha)) {
blob = &qla_fw_blobs[FW_ISP24XX]; blob = &qla_fw_blobs[FW_ISP24XX];
} else if (IS_QLA25XX(ha)) { } else if (IS_QLA25XX(ha)) {
blob = &qla_fw_blobs[FW_ISP25XX]; blob = &qla_fw_blobs[FW_ISP25XX];
...@@ -2792,6 +2804,7 @@ static struct pci_device_id qla2xxx_pci_tbl[] = { ...@@ -2792,6 +2804,7 @@ static struct pci_device_id qla2xxx_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6322) }, { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6322) },
{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2422) }, { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2422) },
{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432) }, { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432) },
{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8432) },
{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5422) }, { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5422) },
{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432) }, { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432) },
{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2532) }, { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2532) },
......
...@@ -553,7 +553,7 @@ qla2xxx_get_flash_info(scsi_qla_host_t *ha) ...@@ -553,7 +553,7 @@ qla2xxx_get_flash_info(scsi_qla_host_t *ha)
struct qla_fdt_layout *fdt; struct qla_fdt_layout *fdt;
uint8_t man_id, flash_id; uint8_t man_id, flash_id;
if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha))
return; return;
wptr = (uint16_t *)ha->request_ring; wptr = (uint16_t *)ha->request_ring;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment