[SCSI] mptfc: set fibre channel fw target missing timers to one second

The fibre channel firmware provides a timer which is similar in purpose
to the fibre channel transport's device loss timer.  The effect of this
timer is to extend the total time that a target will be missing beyond
the value associated with the transport's timer.  This patch changes
the firmware timer to a default of one second which significantly reduces
the lag between when a target goes missing and the notification of the
fibre channel transport.

Signed-off-by: Michael Reed <mdr@sgi.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
Michael Reed 2006-05-24 15:07:24 -05:00 коммит произвёл James Bottomley
Родитель 80d3ac77a8
Коммит ca2f938efe
2 изменённых файлов: 172 добавлений и 9 удалений

Просмотреть файл

@ -487,6 +487,15 @@ typedef struct _RaidCfgData {
int isRaid; /* bit field, 1 if RAID */ int isRaid; /* bit field, 1 if RAID */
}RaidCfgData; }RaidCfgData;
typedef struct _FcCfgData {
/* will ultimately hold fc_port_page0 also */
struct {
FCPortPage1_t *data;
dma_addr_t dma;
int pg_sz;
} fc_port_page1[2];
} FcCfgData;
#define MPT_RPORT_INFO_FLAGS_REGISTERED 0x01 /* rport registered */ #define MPT_RPORT_INFO_FLAGS_REGISTERED 0x01 /* rport registered */
#define MPT_RPORT_INFO_FLAGS_MISSING 0x02 /* missing from DevPage0 scan */ #define MPT_RPORT_INFO_FLAGS_MISSING 0x02 /* missing from DevPage0 scan */
@ -565,6 +574,7 @@ typedef struct _MPT_ADAPTER
SpiCfgData spi_data; /* Scsi config. data */ SpiCfgData spi_data; /* Scsi config. data */
RaidCfgData raid_data; /* Raid config. data */ RaidCfgData raid_data; /* Raid config. data */
SasCfgData sas_data; /* Sas config. data */ SasCfgData sas_data; /* Sas config. data */
FcCfgData fc_data; /* Fc config. data */
MPT_IOCTL *ioctl; /* ioctl data pointer */ MPT_IOCTL *ioctl; /* ioctl data pointer */
struct proc_dir_entry *ioc_dentry; struct proc_dir_entry *ioc_dentry;
struct _MPT_ADAPTER *alt_ioc; /* ptr to 929 bound adapter port */ struct _MPT_ADAPTER *alt_ioc; /* ptr to 929 bound adapter port */

Просмотреть файл

@ -169,13 +169,6 @@ static struct fc_function_template mptfc_transport_functions = {
}; };
/* FIXME! values controlling firmware RESCAN event
* need to be set low to allow dev_loss_tmo to
* work as expected. Currently, firmware doesn't
* notify driver of RESCAN event until some number
* of seconds elapse. This value can be set via
* lsiutil.
*/
static void static void
mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
{ {
@ -700,6 +693,153 @@ mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
return rc; return rc;
} }
static int
mptfc_WriteFcPortPage1(MPT_ADAPTER *ioc, int portnum)
{
ConfigPageHeader_t hdr;
CONFIGPARMS cfg;
int rc;
if (portnum > 1)
return -EINVAL;
if (!(ioc->fc_data.fc_port_page1[portnum].data))
return -EINVAL;
/* get fcport page 1 header */
hdr.PageVersion = 0;
hdr.PageLength = 0;
hdr.PageNumber = 1;
hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
cfg.cfghdr.hdr = &hdr;
cfg.physAddr = -1;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
cfg.dir = 0;
cfg.pageAddr = portnum;
cfg.timeout = 0;
if ((rc = mpt_config(ioc, &cfg)) != 0)
return rc;
if (hdr.PageLength == 0)
return -ENODEV;
if (hdr.PageLength*4 != ioc->fc_data.fc_port_page1[portnum].pg_sz)
return -EINVAL;
cfg.physAddr = ioc->fc_data.fc_port_page1[portnum].dma;
cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
cfg.dir = 1;
rc = mpt_config(ioc, &cfg);
return rc;
}
static int
mptfc_GetFcPortPage1(MPT_ADAPTER *ioc, int portnum)
{
ConfigPageHeader_t hdr;
CONFIGPARMS cfg;
FCPortPage1_t *page1_alloc;
dma_addr_t page1_dma;
int data_sz;
int rc;
if (portnum > 1)
return -EINVAL;
/* get fcport page 1 header */
hdr.PageVersion = 0;
hdr.PageLength = 0;
hdr.PageNumber = 1;
hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
cfg.cfghdr.hdr = &hdr;
cfg.physAddr = -1;
cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
cfg.dir = 0;
cfg.pageAddr = portnum;
cfg.timeout = 0;
if ((rc = mpt_config(ioc, &cfg)) != 0)
return rc;
if (hdr.PageLength == 0)
return -ENODEV;
start_over:
if (ioc->fc_data.fc_port_page1[portnum].data == NULL) {
data_sz = hdr.PageLength * 4;
if (data_sz < sizeof(FCPortPage1_t))
data_sz = sizeof(FCPortPage1_t);
page1_alloc = (FCPortPage1_t *) pci_alloc_consistent(ioc->pcidev,
data_sz,
&page1_dma);
if (!page1_alloc)
return -ENOMEM;
}
else {
page1_alloc = ioc->fc_data.fc_port_page1[portnum].data;
page1_dma = ioc->fc_data.fc_port_page1[portnum].dma;
data_sz = ioc->fc_data.fc_port_page1[portnum].pg_sz;
if (hdr.PageLength * 4 > data_sz) {
ioc->fc_data.fc_port_page1[portnum].data = NULL;
pci_free_consistent(ioc->pcidev, data_sz, (u8 *)
page1_alloc, page1_dma);
goto start_over;
}
}
memset(page1_alloc,0,data_sz);
cfg.physAddr = page1_dma;
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
if ((rc = mpt_config(ioc, &cfg)) == 0) {
ioc->fc_data.fc_port_page1[portnum].data = page1_alloc;
ioc->fc_data.fc_port_page1[portnum].pg_sz = data_sz;
ioc->fc_data.fc_port_page1[portnum].dma = page1_dma;
}
else {
ioc->fc_data.fc_port_page1[portnum].data = NULL;
pci_free_consistent(ioc->pcidev, data_sz, (u8 *)
page1_alloc, page1_dma);
}
return rc;
}
static void
mptfc_SetFcPortPage1_defaults(MPT_ADAPTER *ioc)
{
int ii;
FCPortPage1_t *pp1;
#define MPTFC_FW_DEVICE_TIMEOUT (1)
#define MPTFC_FW_IO_PEND_TIMEOUT (1)
#define ON_FLAGS (MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY)
#define OFF_FLAGS (MPI_FCPORTPAGE1_FLAGS_VERBOSE_RESCAN_EVENTS)
for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
if (mptfc_GetFcPortPage1(ioc, ii) != 0)
continue;
pp1 = ioc->fc_data.fc_port_page1[ii].data;
if ((pp1->InitiatorDeviceTimeout == MPTFC_FW_DEVICE_TIMEOUT)
&& (pp1->InitiatorIoPendTimeout == MPTFC_FW_IO_PEND_TIMEOUT)
&& ((pp1->Flags & ON_FLAGS) == ON_FLAGS)
&& ((pp1->Flags & OFF_FLAGS) == 0))
continue;
pp1->InitiatorDeviceTimeout = MPTFC_FW_DEVICE_TIMEOUT;
pp1->InitiatorIoPendTimeout = MPTFC_FW_IO_PEND_TIMEOUT;
pp1->Flags &= ~OFF_FLAGS;
pp1->Flags |= ON_FLAGS;
mptfc_WriteFcPortPage1(ioc, ii);
}
}
static void static void
mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum) mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
{ {
@ -1000,6 +1140,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
(void) mptfc_GetFcPortPage0(ioc, ii); (void) mptfc_GetFcPortPage0(ioc, ii);
} }
mptfc_SetFcPortPage1_defaults(ioc);
/* /*
* scan for rports - * scan for rports -
@ -1086,6 +1227,7 @@ mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
} }
else { /* MPT_IOC_POST_RESET */ else { /* MPT_IOC_POST_RESET */
mptfc_SetFcPortPage1_defaults(ioc);
spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
if (ioc->fc_rescan_work_q) { if (ioc->fc_rescan_work_q) {
if (ioc->fc_rescan_work_count++ == 0) { if (ioc->fc_rescan_work_count++ == 0) {
@ -1112,8 +1254,8 @@ mptfc_init(void)
show_mptmod_ver(my_NAME, my_VERSION); show_mptmod_ver(my_NAME, my_VERSION);
/* sanity check module parameter */ /* sanity check module parameters */
if (mptfc_dev_loss_tmo == 0) if (mptfc_dev_loss_tmo <= 0)
mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;
mptfc_transport_template = mptfc_transport_template =
@ -1156,6 +1298,7 @@ mptfc_remove(struct pci_dev *pdev)
struct mptfc_rport_info *p, *n; struct mptfc_rport_info *p, *n;
struct workqueue_struct *work_q; struct workqueue_struct *work_q;
unsigned long flags; unsigned long flags;
int ii;
/* destroy workqueue */ /* destroy workqueue */
if ((work_q=ioc->fc_rescan_work_q)) { if ((work_q=ioc->fc_rescan_work_q)) {
@ -1172,6 +1315,16 @@ mptfc_remove(struct pci_dev *pdev)
kfree(p); kfree(p);
} }
for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
if (ioc->fc_data.fc_port_page1[ii].data) {
pci_free_consistent(ioc->pcidev,
ioc->fc_data.fc_port_page1[ii].pg_sz,
(u8 *) ioc->fc_data.fc_port_page1[ii].data,
ioc->fc_data.fc_port_page1[ii].dma);
ioc->fc_data.fc_port_page1[ii].data = NULL;
}
}
mptscsih_remove(pdev); mptscsih_remove(pdev);
} }