Skip to content

Commit

Permalink
[SCSI] qla2xxx: Handle change notifications based on switch scan resu…
Browse files Browse the repository at this point in the history
…lts.

Instead of processing each RSCN individually, use only the name server results
from the switch to tell the existance of a given fcport.

Signed-off-by: Arun Easi <arun.easi@qlogic.com>
Signed-off-by: Chad Dupuis <chad.dupuis@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
  • Loading branch information
Arun Easi authored and James Bottomley committed Feb 19, 2012
1 parent 18f509d commit b3b02e6
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 144 deletions.
9 changes: 1 addition & 8 deletions drivers/scsi/qla2xxx/qla_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@
#define WWN_SIZE 8 /* Size of WWPN, WWN & WWNN */
#define MAX_FIBRE_DEVICES 512
#define MAX_FIBRE_LUNS 0xFFFF
#define MAX_RSCN_COUNT 32
#define MAX_HOST_COUNT 16

/*
Expand Down Expand Up @@ -1720,6 +1719,7 @@ typedef struct fc_port {

uint16_t vp_idx;
uint8_t fc4_type;
uint8_t scan_state;
} fc_port_t;

/*
Expand Down Expand Up @@ -2877,7 +2877,6 @@ typedef struct scsi_qla_host {
volatile struct {
uint32_t init_done :1;
uint32_t online :1;
uint32_t rscn_queue_overflow :1;
uint32_t reset_active :1;

uint32_t management_server_logged_in :1;
Expand Down Expand Up @@ -2931,11 +2930,6 @@ typedef struct scsi_qla_host {



/* RSCN queue. */
uint32_t rscn_queue[MAX_RSCN_COUNT];
uint8_t rscn_in_ptr;
uint8_t rscn_out_ptr;

/* Timeout timers. */
uint8_t loop_down_abort_time; /* port down timer */
atomic_t loop_down_timer; /* loop down timer */
Expand Down Expand Up @@ -3031,7 +3025,6 @@ typedef struct scsi_qla_host {
#define QLA_ABORTED 0x105
#define QLA_SUSPENDED 0x106
#define QLA_BUSY 0x107
#define QLA_RSCNS_HANDLED 0x108
#define QLA_ALREADY_REGISTERED 0x109

#define NVRAM_DELAY() udelay(10)
Expand Down
136 changes: 12 additions & 124 deletions drivers/scsi/qla2xxx/qla_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ static int qla2x00_configure_loop(scsi_qla_host_t *);
static int qla2x00_configure_local_loop(scsi_qla_host_t *);
static int qla2x00_configure_fabric(scsi_qla_host_t *);
static int qla2x00_find_all_fabric_devs(scsi_qla_host_t *, struct list_head *);
static int qla2x00_device_resync(scsi_qla_host_t *);
static int qla2x00_fabric_dev_login(scsi_qla_host_t *, fc_port_t *,
uint16_t *);

Expand Down Expand Up @@ -1755,7 +1754,6 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
struct qla_hw_data *ha = vha->hw;
struct req_que *req;
struct rsp_que *rsp;
struct scsi_qla_host *vp;
struct mid_init_cb_24xx *mid_init_cb =
(struct mid_init_cb_24xx *) ha->init_cb;

Expand Down Expand Up @@ -1786,11 +1784,6 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
}

spin_lock(&ha->vport_slock);
/* Clear RSCN queue. */
list_for_each_entry(vp, &ha->vp_list, list) {
vp->rscn_in_ptr = 0;
vp->rscn_out_ptr = 0;
}

spin_unlock(&ha->vport_slock);

Expand Down Expand Up @@ -2551,13 +2544,11 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
if (ha->current_topology == ISP_CFG_FL &&
(test_bit(LOCAL_LOOP_UPDATE, &flags))) {

vha->flags.rscn_queue_overflow = 1;
set_bit(RSCN_UPDATE, &flags);

} else if (ha->current_topology == ISP_CFG_F &&
(test_bit(LOCAL_LOOP_UPDATE, &flags))) {

vha->flags.rscn_queue_overflow = 1;
set_bit(RSCN_UPDATE, &flags);
clear_bit(LOCAL_LOOP_UPDATE, &flags);

Expand All @@ -2567,7 +2558,6 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
} else if (!vha->flags.online ||
(test_bit(ABORT_ISP_ACTIVE, &flags))) {

vha->flags.rscn_queue_overflow = 1;
set_bit(RSCN_UPDATE, &flags);
set_bit(LOCAL_LOOP_UPDATE, &flags);
}
Expand Down Expand Up @@ -2617,8 +2607,6 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
if (test_bit(RSCN_UPDATE, &save_flags)) {
set_bit(RSCN_UPDATE, &vha->dpc_flags);
if (!IS_ALOGIO_CAPABLE(ha))
vha->flags.rscn_queue_overflow = 1;
}
}

Expand Down Expand Up @@ -2926,7 +2914,7 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
static int
qla2x00_configure_fabric(scsi_qla_host_t *vha)
{
int rval, rval2;
int rval;
fc_port_t *fcport, *fcptemp;
uint16_t next_loopid;
uint16_t mb[MAILBOX_REGISTER_COUNT];
Expand All @@ -2950,12 +2938,6 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
}
vha->device_flags |= SWITCH_FOUND;

/* Mark devices that need re-synchronization. */
rval2 = qla2x00_device_resync(vha);
if (rval2 == QLA_RSCNS_HANDLED) {
/* No point doing the scan, just continue. */
return (QLA_SUCCESS);
}
do {
/* FDMI support. */
if (ql2xfdmienable &&
Expand Down Expand Up @@ -2999,6 +2981,13 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
}
}

#define QLA_FCPORT_SCAN 1
#define QLA_FCPORT_FOUND 2

list_for_each_entry(fcport, &vha->vp_fcports, list) {
fcport->scan_state = QLA_FCPORT_SCAN;
}

rval = qla2x00_find_all_fabric_devs(vha, &new_fcports);
if (rval != QLA_SUCCESS)
break;
Expand All @@ -3014,7 +3003,8 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
if ((fcport->flags & FCF_FABRIC_DEVICE) == 0)
continue;

if (atomic_read(&fcport->state) == FCS_DEVICE_LOST) {
if (fcport->scan_state == QLA_FCPORT_SCAN &&
atomic_read(&fcport->state) == FCS_ONLINE) {
qla2x00_mark_device_lost(vha, fcport,
ql2xplogiabsentdevice, 0);
if (fcport->loop_id != FC_NO_LOOP_ID &&
Expand Down Expand Up @@ -3287,6 +3277,8 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
WWN_SIZE))
continue;

fcport->scan_state = QLA_FCPORT_FOUND;

found++;

/* Update port state. */
Expand Down Expand Up @@ -3442,110 +3434,6 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev)
return (rval);
}

/*
* qla2x00_device_resync
* Marks devices in the database that needs resynchronization.
*
* Input:
* ha = adapter block pointer.
*
* Context:
* Kernel context.
*/
static int
qla2x00_device_resync(scsi_qla_host_t *vha)
{
int rval;
uint32_t mask;
fc_port_t *fcport;
uint32_t rscn_entry;
uint8_t rscn_out_iter;
uint8_t format;
port_id_t d_id = {};

rval = QLA_RSCNS_HANDLED;

while (vha->rscn_out_ptr != vha->rscn_in_ptr ||
vha->flags.rscn_queue_overflow) {

rscn_entry = vha->rscn_queue[vha->rscn_out_ptr];
format = MSB(MSW(rscn_entry));
d_id.b.domain = LSB(MSW(rscn_entry));
d_id.b.area = MSB(LSW(rscn_entry));
d_id.b.al_pa = LSB(LSW(rscn_entry));

ql_dbg(ql_dbg_disc, vha, 0x2020,
"RSCN queue entry[%d] = [%02x/%02x%02x%02x].\n",
vha->rscn_out_ptr, format, d_id.b.domain, d_id.b.area,
d_id.b.al_pa);

vha->rscn_out_ptr++;
if (vha->rscn_out_ptr == MAX_RSCN_COUNT)
vha->rscn_out_ptr = 0;

/* Skip duplicate entries. */
for (rscn_out_iter = vha->rscn_out_ptr;
!vha->flags.rscn_queue_overflow &&
rscn_out_iter != vha->rscn_in_ptr;
rscn_out_iter = (rscn_out_iter ==
(MAX_RSCN_COUNT - 1)) ? 0: rscn_out_iter + 1) {

if (rscn_entry != vha->rscn_queue[rscn_out_iter])
break;

ql_dbg(ql_dbg_disc, vha, 0x2021,
"Skipping duplicate RSCN queue entry found at "
"[%d].\n", rscn_out_iter);

vha->rscn_out_ptr = rscn_out_iter;
}

/* Queue overflow, set switch default case. */
if (vha->flags.rscn_queue_overflow) {
ql_dbg(ql_dbg_disc, vha, 0x2022,
"device_resync: rscn overflow.\n");

format = 3;
vha->flags.rscn_queue_overflow = 0;
}

switch (format) {
case 0:
mask = 0xffffff;
break;
case 1:
mask = 0xffff00;
break;
case 2:
mask = 0xff0000;
break;
default:
mask = 0x0;
d_id.b24 = 0;
vha->rscn_out_ptr = vha->rscn_in_ptr;
break;
}

rval = QLA_SUCCESS;

list_for_each_entry(fcport, &vha->vp_fcports, list) {
if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 ||
(fcport->d_id.b24 & mask) != d_id.b24 ||
fcport->port_type == FCT_BROADCAST)
continue;

if (atomic_read(&fcport->state) == FCS_ONLINE) {
if (format != 3 ||
fcport->port_type != FCT_INITIATOR) {
qla2x00_mark_device_lost(vha, fcport,
0, 0);
}
}
}
}
return (rval);
}

/*
* qla2x00_fabric_dev_login
* Login fabric target device and update FC port database.
Expand Down
12 changes: 0 additions & 12 deletions drivers/scsi/qla2xxx/qla_isr.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,6 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
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;

/* Setup to process RIO completion. */
Expand Down Expand Up @@ -685,8 +684,6 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)

qla2x00_mark_all_devices_lost(vha, 1);

vha->flags.rscn_queue_overflow = 1;

set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
break;
Expand Down Expand Up @@ -715,15 +712,6 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)

/* Ignore reserved bits from RSCN-payload. */
rscn_entry = ((mb[1] & 0x3ff) << 16) | mb[2];
rscn_queue_index = vha->rscn_in_ptr + 1;
if (rscn_queue_index == MAX_RSCN_COUNT)
rscn_queue_index = 0;
if (rscn_queue_index != vha->rscn_out_ptr) {
vha->rscn_queue[vha->rscn_in_ptr] = rscn_entry;
vha->rscn_in_ptr = rscn_queue_index;
} else {
vha->flags.rscn_queue_overflow = 1;
}

atomic_set(&vha->loop_down_timer, 0);
vha->flags.management_server_logged_in = 0;
Expand Down

0 comments on commit b3b02e6

Please sign in to comment.