diff options
author | Kashyap, Desai <kashyap.desai@lsi.com> | 2009-05-29 07:10:57 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-06-09 18:26:20 -0400 |
commit | f0f09d3b3f06900d64971625d6753dea0623ed45 (patch) | |
tree | 896237d53275eeb6b4484c2cb747f0b333157c30 /drivers/message/fusion/mptbase.c | |
parent | fd76175a7d3abf4d14df17f5f4c7e68b466b455d (diff) |
[SCSI] mpt fusion: config path optimized, completion queue is used
1) Previously we had mutliple #defines to use same values.
Now those #defines are optimized.
MPT_IOCTL_STATUS_* is removed and MPT_MGMT_STATUS_* are new
#defines.
2.) config path is optimized.
Instead of wait Queue and timer, using completion Q.
3.) mpt_timer_expired is not used.
[jejb: elide patch to eliminate mpt_timer_expired]
Signed-off-by: Kashyap Desai <kadesai@lsi.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/message/fusion/mptbase.c')
-rw-r--r-- | drivers/message/fusion/mptbase.c | 456 |
1 files changed, 215 insertions, 241 deletions
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 0d2fb0eb34b9..e63a6260b0a0 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c | |||
@@ -146,7 +146,6 @@ static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS]; | |||
146 | static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS]; | 146 | static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS]; |
147 | static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS]; | 147 | static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS]; |
148 | 148 | ||
149 | static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq); | ||
150 | 149 | ||
151 | /* | 150 | /* |
152 | * Driver Callback Index's | 151 | * Driver Callback Index's |
@@ -159,7 +158,8 @@ static u8 last_drv_idx; | |||
159 | * Forward protos... | 158 | * Forward protos... |
160 | */ | 159 | */ |
161 | static irqreturn_t mpt_interrupt(int irq, void *bus_id); | 160 | static irqreturn_t mpt_interrupt(int irq, void *bus_id); |
162 | static int mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply); | 161 | static int mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, |
162 | MPT_FRAME_HDR *reply); | ||
163 | static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, | 163 | static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, |
164 | u32 *req, int replyBytes, u16 *u16reply, int maxwait, | 164 | u32 *req, int replyBytes, u16 *u16reply, int maxwait, |
165 | int sleepFlag); | 165 | int sleepFlag); |
@@ -190,7 +190,6 @@ static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum); | |||
190 | static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum); | 190 | static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum); |
191 | static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc); | 191 | static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc); |
192 | static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc); | 192 | static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc); |
193 | static void mpt_timer_expired(unsigned long data); | ||
194 | static void mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc); | 193 | static void mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc); |
195 | static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch, | 194 | static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch, |
196 | int sleepFlag); | 195 | int sleepFlag); |
@@ -559,9 +558,9 @@ mpt_interrupt(int irq, void *bus_id) | |||
559 | 558 | ||
560 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 559 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
561 | /** | 560 | /** |
562 | * mpt_base_reply - MPT base driver's callback routine | 561 | * mptbase_reply - MPT base driver's callback routine |
563 | * @ioc: Pointer to MPT_ADAPTER structure | 562 | * @ioc: Pointer to MPT_ADAPTER structure |
564 | * @mf: Pointer to original MPT request frame | 563 | * @req: Pointer to original MPT request frame |
565 | * @reply: Pointer to MPT reply frame (NULL if TurboReply) | 564 | * @reply: Pointer to MPT reply frame (NULL if TurboReply) |
566 | * | 565 | * |
567 | * MPT base driver's callback routine; all base driver | 566 | * MPT base driver's callback routine; all base driver |
@@ -572,122 +571,49 @@ mpt_interrupt(int irq, void *bus_id) | |||
572 | * should be freed, or 0 if it shouldn't. | 571 | * should be freed, or 0 if it shouldn't. |
573 | */ | 572 | */ |
574 | static int | 573 | static int |
575 | mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) | 574 | mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply) |
576 | { | 575 | { |
576 | EventNotificationReply_t *pEventReply; | ||
577 | u8 event; | ||
578 | int evHandlers; | ||
577 | int freereq = 1; | 579 | int freereq = 1; |
578 | u8 func; | ||
579 | |||
580 | dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply() called\n", ioc->name)); | ||
581 | #ifdef CONFIG_FUSION_LOGGING | ||
582 | if ((ioc->debug_level & MPT_DEBUG_MSG_FRAME) && | ||
583 | !(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) { | ||
584 | dmfprintk(ioc, printk(MYIOC_s_INFO_FMT ": Original request frame (@%p) header\n", | ||
585 | ioc->name, mf)); | ||
586 | DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)mf); | ||
587 | } | ||
588 | #endif | ||
589 | |||
590 | func = reply->u.hdr.Function; | ||
591 | dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply, Function=%02Xh\n", | ||
592 | ioc->name, func)); | ||
593 | |||
594 | if (func == MPI_FUNCTION_EVENT_NOTIFICATION) { | ||
595 | EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply; | ||
596 | int evHandlers = 0; | ||
597 | int results; | ||
598 | |||
599 | results = ProcessEventNotification(ioc, pEvReply, &evHandlers); | ||
600 | if (results != evHandlers) { | ||
601 | /* CHECKME! Any special handling needed here? */ | ||
602 | devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n", | ||
603 | ioc->name, evHandlers, results)); | ||
604 | } | ||
605 | 580 | ||
606 | /* | 581 | switch (reply->u.hdr.Function) { |
607 | * Hmmm... It seems that EventNotificationReply is an exception | 582 | case MPI_FUNCTION_EVENT_NOTIFICATION: |
608 | * to the rule of one reply per request. | 583 | pEventReply = (EventNotificationReply_t *)reply; |
609 | */ | 584 | evHandlers = 0; |
610 | if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) { | 585 | ProcessEventNotification(ioc, pEventReply, &evHandlers); |
586 | event = le32_to_cpu(pEventReply->Event) & 0xFF; | ||
587 | if (pEventReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) | ||
611 | freereq = 0; | 588 | freereq = 0; |
612 | } else { | 589 | if (event != MPI_EVENT_EVENT_CHANGE) |
613 | devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n", | 590 | break; |
614 | ioc->name, pEvReply)); | 591 | case MPI_FUNCTION_CONFIG: |
615 | } | 592 | case MPI_FUNCTION_SAS_IO_UNIT_CONTROL: |
616 | 593 | ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD; | |
617 | #ifdef CONFIG_PROC_FS | 594 | if (reply) { |
618 | // LogEvent(ioc, pEvReply); | 595 | ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_RF_VALID; |
619 | #endif | 596 | memcpy(ioc->mptbase_cmds.reply, reply, |
620 | 597 | min(MPT_DEFAULT_FRAME_SIZE, | |
621 | } else if (func == MPI_FUNCTION_EVENT_ACK) { | 598 | 4 * reply->u.reply.MsgLength)); |
622 | dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply, EventAck reply received\n", | ||
623 | ioc->name)); | ||
624 | } else if (func == MPI_FUNCTION_CONFIG) { | ||
625 | CONFIGPARMS *pCfg; | ||
626 | unsigned long flags; | ||
627 | |||
628 | dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "config_complete (mf=%p,mr=%p)\n", | ||
629 | ioc->name, mf, reply)); | ||
630 | |||
631 | pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *))); | ||
632 | |||
633 | if (pCfg) { | ||
634 | /* disable timer and remove from linked list */ | ||
635 | del_timer(&pCfg->timer); | ||
636 | |||
637 | spin_lock_irqsave(&ioc->FreeQlock, flags); | ||
638 | list_del(&pCfg->linkage); | ||
639 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
640 | |||
641 | /* | ||
642 | * If IOC Status is SUCCESS, save the header | ||
643 | * and set the status code to GOOD. | ||
644 | */ | ||
645 | pCfg->status = MPT_CONFIG_ERROR; | ||
646 | if (reply) { | ||
647 | ConfigReply_t *pReply = (ConfigReply_t *)reply; | ||
648 | u16 status; | ||
649 | |||
650 | status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK; | ||
651 | dcprintk(ioc, printk(MYIOC_s_NOTE_FMT " IOCStatus=%04xh, IOCLogInfo=%08xh\n", | ||
652 | ioc->name, status, le32_to_cpu(pReply->IOCLogInfo))); | ||
653 | |||
654 | pCfg->status = status; | ||
655 | if (status == MPI_IOCSTATUS_SUCCESS) { | ||
656 | if ((pReply->Header.PageType & | ||
657 | MPI_CONFIG_PAGETYPE_MASK) == | ||
658 | MPI_CONFIG_PAGETYPE_EXTENDED) { | ||
659 | pCfg->cfghdr.ehdr->ExtPageLength = | ||
660 | le16_to_cpu(pReply->ExtPageLength); | ||
661 | pCfg->cfghdr.ehdr->ExtPageType = | ||
662 | pReply->ExtPageType; | ||
663 | } | ||
664 | pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion; | ||
665 | |||
666 | /* If this is a regular header, save PageLength. */ | ||
667 | /* LMP Do this better so not using a reserved field! */ | ||
668 | pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength; | ||
669 | pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber; | ||
670 | pCfg->cfghdr.hdr->PageType = pReply->Header.PageType; | ||
671 | } | ||
672 | } | ||
673 | |||
674 | /* | ||
675 | * Wake up the original calling thread | ||
676 | */ | ||
677 | pCfg->wait_done = 1; | ||
678 | wake_up(&mpt_waitq); | ||
679 | } | 599 | } |
680 | } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) { | 600 | if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_PENDING) { |
681 | /* we should be always getting a reply frame */ | 601 | ioc->mptbase_cmds.status &= ~MPT_MGMT_STATUS_PENDING; |
682 | memcpy(ioc->persist_reply_frame, reply, | 602 | complete(&ioc->mptbase_cmds.done); |
683 | min(MPT_DEFAULT_FRAME_SIZE, | 603 | } else |
684 | 4*reply->u.reply.MsgLength)); | 604 | freereq = 0; |
685 | del_timer(&ioc->persist_timer); | 605 | if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_FREE_MF) |
686 | ioc->persist_wait_done = 1; | 606 | freereq = 1; |
687 | wake_up(&mpt_waitq); | 607 | break; |
688 | } else { | 608 | case MPI_FUNCTION_EVENT_ACK: |
689 | printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n", | 609 | devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
690 | ioc->name, func); | 610 | "EventAck reply received\n", ioc->name)); |
611 | break; | ||
612 | default: | ||
613 | printk(MYIOC_s_ERR_FMT | ||
614 | "Unexpected msg function (=%02Xh) reply received!\n", | ||
615 | ioc->name, reply->u.hdr.Function); | ||
616 | break; | ||
691 | } | 617 | } |
692 | 618 | ||
693 | /* | 619 | /* |
@@ -1849,6 +1775,9 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1849 | spin_lock_init(&ioc->diagLock); | 1775 | spin_lock_init(&ioc->diagLock); |
1850 | spin_lock_init(&ioc->initializing_hba_lock); | 1776 | spin_lock_init(&ioc->initializing_hba_lock); |
1851 | 1777 | ||
1778 | mutex_init(&ioc->mptbase_cmds.mutex); | ||
1779 | init_completion(&ioc->mptbase_cmds.done); | ||
1780 | |||
1852 | /* Initialize the event logging. | 1781 | /* Initialize the event logging. |
1853 | */ | 1782 | */ |
1854 | ioc->eventTypes = 0; /* None */ | 1783 | ioc->eventTypes = 0; /* None */ |
@@ -1866,10 +1795,6 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1866 | */ | 1795 | */ |
1867 | memset(&ioc->spi_data, 0, sizeof(SpiCfgData)); | 1796 | memset(&ioc->spi_data, 0, sizeof(SpiCfgData)); |
1868 | 1797 | ||
1869 | /* Initialize the running configQ head. | ||
1870 | */ | ||
1871 | INIT_LIST_HEAD(&ioc->configQ); | ||
1872 | |||
1873 | /* Initialize the fc rport list head. | 1798 | /* Initialize the fc rport list head. |
1874 | */ | 1799 | */ |
1875 | INIT_LIST_HEAD(&ioc->fc_rports); | 1800 | INIT_LIST_HEAD(&ioc->fc_rports); |
@@ -5013,7 +4938,14 @@ mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode) | |||
5013 | SasIoUnitControlReply_t *sasIoUnitCntrReply; | 4938 | SasIoUnitControlReply_t *sasIoUnitCntrReply; |
5014 | MPT_FRAME_HDR *mf = NULL; | 4939 | MPT_FRAME_HDR *mf = NULL; |
5015 | MPIHeader_t *mpi_hdr; | 4940 | MPIHeader_t *mpi_hdr; |
4941 | int ret = 0; | ||
4942 | unsigned long timeleft; | ||
4943 | |||
4944 | mutex_lock(&ioc->mptbase_cmds.mutex); | ||
5016 | 4945 | ||
4946 | /* init the internal cmd struct */ | ||
4947 | memset(ioc->mptbase_cmds.reply, 0 , MPT_DEFAULT_FRAME_SIZE); | ||
4948 | INITIALIZE_MGMT_STATUS(ioc->mptbase_cmds.status) | ||
5017 | 4949 | ||
5018 | /* insure garbage is not sent to fw */ | 4950 | /* insure garbage is not sent to fw */ |
5019 | switch(persist_opcode) { | 4951 | switch(persist_opcode) { |
@@ -5023,17 +4955,19 @@ mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode) | |||
5023 | break; | 4955 | break; |
5024 | 4956 | ||
5025 | default: | 4957 | default: |
5026 | return -1; | 4958 | ret = -1; |
5027 | break; | 4959 | goto out; |
5028 | } | 4960 | } |
5029 | 4961 | ||
5030 | printk("%s: persist_opcode=%x\n",__func__, persist_opcode); | 4962 | printk(KERN_DEBUG "%s: persist_opcode=%x\n", |
4963 | __func__, persist_opcode); | ||
5031 | 4964 | ||
5032 | /* Get a MF for this command. | 4965 | /* Get a MF for this command. |
5033 | */ | 4966 | */ |
5034 | if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { | 4967 | if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { |
5035 | printk("%s: no msg frames!\n",__func__); | 4968 | printk(KERN_DEBUG "%s: no msg frames!\n", __func__); |
5036 | return -1; | 4969 | ret = -1; |
4970 | goto out; | ||
5037 | } | 4971 | } |
5038 | 4972 | ||
5039 | mpi_hdr = (MPIHeader_t *) mf; | 4973 | mpi_hdr = (MPIHeader_t *) mf; |
@@ -5043,27 +4977,42 @@ mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode) | |||
5043 | sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext; | 4977 | sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext; |
5044 | sasIoUnitCntrReq->Operation = persist_opcode; | 4978 | sasIoUnitCntrReq->Operation = persist_opcode; |
5045 | 4979 | ||
5046 | init_timer(&ioc->persist_timer); | ||
5047 | ioc->persist_timer.data = (unsigned long) ioc; | ||
5048 | ioc->persist_timer.function = mpt_timer_expired; | ||
5049 | ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */; | ||
5050 | ioc->persist_wait_done=0; | ||
5051 | add_timer(&ioc->persist_timer); | ||
5052 | mpt_put_msg_frame(mpt_base_index, ioc, mf); | 4980 | mpt_put_msg_frame(mpt_base_index, ioc, mf); |
5053 | wait_event(mpt_waitq, ioc->persist_wait_done); | 4981 | timeleft = wait_for_completion_timeout(&ioc->mptbase_cmds.done, 10*HZ); |
4982 | if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { | ||
4983 | ret = -ETIME; | ||
4984 | printk(KERN_DEBUG "%s: failed\n", __func__); | ||
4985 | if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) | ||
4986 | goto out; | ||
4987 | if (!timeleft) { | ||
4988 | printk(KERN_DEBUG "%s: Issuing Reset from %s!!\n", | ||
4989 | ioc->name, __func__); | ||
4990 | mpt_HardResetHandler(ioc, CAN_SLEEP); | ||
4991 | mpt_free_msg_frame(ioc, mf); | ||
4992 | } | ||
4993 | goto out; | ||
4994 | } | ||
4995 | |||
4996 | if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_RF_VALID)) { | ||
4997 | ret = -1; | ||
4998 | goto out; | ||
4999 | } | ||
5054 | 5000 | ||
5055 | sasIoUnitCntrReply = | 5001 | sasIoUnitCntrReply = |
5056 | (SasIoUnitControlReply_t *)ioc->persist_reply_frame; | 5002 | (SasIoUnitControlReply_t *)ioc->mptbase_cmds.reply; |
5057 | if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) { | 5003 | if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) { |
5058 | printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n", | 5004 | printk(KERN_DEBUG "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n", |
5059 | __func__, | 5005 | __func__, sasIoUnitCntrReply->IOCStatus, |
5060 | sasIoUnitCntrReply->IOCStatus, | ||
5061 | sasIoUnitCntrReply->IOCLogInfo); | 5006 | sasIoUnitCntrReply->IOCLogInfo); |
5062 | return -1; | 5007 | printk(KERN_DEBUG "%s: failed\n", __func__); |
5063 | } | 5008 | ret = -1; |
5009 | } else | ||
5010 | printk(KERN_DEBUG "%s: success\n", __func__); | ||
5011 | out: | ||
5064 | 5012 | ||
5065 | printk("%s: success\n",__func__); | 5013 | CLEAR_MGMT_STATUS(ioc->mptbase_cmds.status) |
5066 | return 0; | 5014 | mutex_unlock(&ioc->mptbase_cmds.mutex); |
5015 | return ret; | ||
5067 | } | 5016 | } |
5068 | 5017 | ||
5069 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 5018 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
@@ -6066,7 +6015,7 @@ SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp) | |||
6066 | 6015 | ||
6067 | if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { | 6016 | if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { |
6068 | dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n", | 6017 | dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n", |
6069 | ioc->name,__func__)); | 6018 | ioc->name, __func__)); |
6070 | return -1; | 6019 | return -1; |
6071 | } | 6020 | } |
6072 | 6021 | ||
@@ -6103,12 +6052,18 @@ int | |||
6103 | mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) | 6052 | mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) |
6104 | { | 6053 | { |
6105 | Config_t *pReq; | 6054 | Config_t *pReq; |
6055 | ConfigReply_t *pReply; | ||
6106 | ConfigExtendedPageHeader_t *pExtHdr = NULL; | 6056 | ConfigExtendedPageHeader_t *pExtHdr = NULL; |
6107 | MPT_FRAME_HDR *mf; | 6057 | MPT_FRAME_HDR *mf; |
6108 | unsigned long flags; | 6058 | int ii; |
6109 | int ii, rc; | ||
6110 | int flagsLength; | 6059 | int flagsLength; |
6060 | long timeout; | ||
6061 | int ret; | ||
6062 | u8 page_type = 0, extend_page; | ||
6063 | unsigned long timeleft; | ||
6111 | int in_isr; | 6064 | int in_isr; |
6065 | u8 issue_hard_reset = 0; | ||
6066 | u8 retry_count = 0; | ||
6112 | 6067 | ||
6113 | /* Prevent calling wait_event() (below), if caller happens | 6068 | /* Prevent calling wait_event() (below), if caller happens |
6114 | * to be in ISR context, because that is fatal! | 6069 | * to be in ISR context, because that is fatal! |
@@ -6120,13 +6075,31 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) | |||
6120 | return -EPERM; | 6075 | return -EPERM; |
6121 | } | 6076 | } |
6122 | 6077 | ||
6078 | /* don't send if no chance of success */ | ||
6079 | if (!ioc->active || | ||
6080 | mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_OPERATIONAL) { | ||
6081 | dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
6082 | "%s: ioc not operational, %d, %xh\n", | ||
6083 | ioc->name, __func__, ioc->active, | ||
6084 | mpt_GetIocState(ioc, 0))); | ||
6085 | return -EFAULT; | ||
6086 | } | ||
6087 | |||
6088 | retry_config: | ||
6089 | mutex_lock(&ioc->mptbase_cmds.mutex); | ||
6090 | /* init the internal cmd struct */ | ||
6091 | memset(ioc->mptbase_cmds.reply, 0 , MPT_DEFAULT_FRAME_SIZE); | ||
6092 | INITIALIZE_MGMT_STATUS(ioc->mptbase_cmds.status) | ||
6093 | |||
6123 | /* Get and Populate a free Frame | 6094 | /* Get and Populate a free Frame |
6124 | */ | 6095 | */ |
6125 | if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { | 6096 | if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { |
6126 | dcprintk(ioc, printk(MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n", | 6097 | dcprintk(ioc, printk(MYIOC_s_WARN_FMT |
6127 | ioc->name)); | 6098 | "mpt_config: no msg frames!\n", ioc->name)); |
6128 | return -EAGAIN; | 6099 | ret = -EAGAIN; |
6100 | goto out; | ||
6129 | } | 6101 | } |
6102 | |||
6130 | pReq = (Config_t *)mf; | 6103 | pReq = (Config_t *)mf; |
6131 | pReq->Action = pCfg->action; | 6104 | pReq->Action = pCfg->action; |
6132 | pReq->Reserved = 0; | 6105 | pReq->Reserved = 0; |
@@ -6152,7 +6125,9 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) | |||
6152 | pReq->ExtPageType = pExtHdr->ExtPageType; | 6125 | pReq->ExtPageType = pExtHdr->ExtPageType; |
6153 | pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; | 6126 | pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; |
6154 | 6127 | ||
6155 | /* Page Length must be treated as a reserved field for the extended header. */ | 6128 | /* Page Length must be treated as a reserved field for the |
6129 | * extended header. | ||
6130 | */ | ||
6156 | pReq->Header.PageLength = 0; | 6131 | pReq->Header.PageLength = 0; |
6157 | } | 6132 | } |
6158 | 6133 | ||
@@ -6165,78 +6140,91 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) | |||
6165 | else | 6140 | else |
6166 | flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ; | 6141 | flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ; |
6167 | 6142 | ||
6168 | if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) { | 6143 | if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == |
6144 | MPI_CONFIG_PAGETYPE_EXTENDED) { | ||
6169 | flagsLength |= pExtHdr->ExtPageLength * 4; | 6145 | flagsLength |= pExtHdr->ExtPageLength * 4; |
6170 | 6146 | page_type = pReq->ExtPageType; | |
6171 | dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Config request type %d, page %d and action %d\n", | 6147 | extend_page = 1; |
6172 | ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action)); | 6148 | } else { |
6173 | } | ||
6174 | else { | ||
6175 | flagsLength |= pCfg->cfghdr.hdr->PageLength * 4; | 6149 | flagsLength |= pCfg->cfghdr.hdr->PageLength * 4; |
6176 | 6150 | page_type = pReq->Header.PageType; | |
6177 | dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Config request type %d, page %d and action %d\n", | 6151 | extend_page = 0; |
6178 | ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action)); | ||
6179 | } | 6152 | } |
6180 | 6153 | ||
6181 | ioc->add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr); | 6154 | dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
6182 | 6155 | "Sending Config request type 0x%x, page 0x%x and action %d\n", | |
6183 | /* Append pCfg pointer to end of mf | 6156 | ioc->name, page_type, pReq->Header.PageNumber, pReq->Action)); |
6184 | */ | ||
6185 | *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) = (void *) pCfg; | ||
6186 | |||
6187 | /* Initalize the timer | ||
6188 | */ | ||
6189 | init_timer_on_stack(&pCfg->timer); | ||
6190 | pCfg->timer.data = (unsigned long) ioc; | ||
6191 | pCfg->timer.function = mpt_timer_expired; | ||
6192 | pCfg->wait_done = 0; | ||
6193 | |||
6194 | /* Set the timer; ensure 10 second minimum */ | ||
6195 | if (pCfg->timeout < 10) | ||
6196 | pCfg->timer.expires = jiffies + HZ*10; | ||
6197 | else | ||
6198 | pCfg->timer.expires = jiffies + HZ*pCfg->timeout; | ||
6199 | |||
6200 | /* Add to end of Q, set timer and then issue this command */ | ||
6201 | spin_lock_irqsave(&ioc->FreeQlock, flags); | ||
6202 | list_add_tail(&pCfg->linkage, &ioc->configQ); | ||
6203 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
6204 | 6157 | ||
6205 | add_timer(&pCfg->timer); | 6158 | ioc->add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr); |
6159 | timeout = (pCfg->timeout < 15) ? HZ*15 : HZ*pCfg->timeout; | ||
6206 | mpt_put_msg_frame(mpt_base_index, ioc, mf); | 6160 | mpt_put_msg_frame(mpt_base_index, ioc, mf); |
6207 | wait_event(mpt_waitq, pCfg->wait_done); | 6161 | timeleft = wait_for_completion_timeout(&ioc->mptbase_cmds.done, |
6208 | 6162 | timeout); | |
6209 | /* mf has been freed - do not access */ | 6163 | if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { |
6164 | ret = -ETIME; | ||
6165 | dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
6166 | "Failed Sending Config request type 0x%x, page 0x%x," | ||
6167 | " action %d, status %xh, time left %ld\n\n", | ||
6168 | ioc->name, page_type, pReq->Header.PageNumber, | ||
6169 | pReq->Action, ioc->mptbase_cmds.status, timeleft)); | ||
6170 | if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) | ||
6171 | goto out; | ||
6172 | if (!timeleft) | ||
6173 | issue_hard_reset = 1; | ||
6174 | goto out; | ||
6175 | } | ||
6210 | 6176 | ||
6211 | rc = pCfg->status; | 6177 | if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_RF_VALID)) { |
6178 | ret = -1; | ||
6179 | goto out; | ||
6180 | } | ||
6181 | pReply = (ConfigReply_t *)ioc->mptbase_cmds.reply; | ||
6182 | ret = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK; | ||
6183 | if (ret == MPI_IOCSTATUS_SUCCESS) { | ||
6184 | if (extend_page) { | ||
6185 | pCfg->cfghdr.ehdr->ExtPageLength = | ||
6186 | le16_to_cpu(pReply->ExtPageLength); | ||
6187 | pCfg->cfghdr.ehdr->ExtPageType = | ||
6188 | pReply->ExtPageType; | ||
6189 | } | ||
6190 | pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion; | ||
6191 | pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength; | ||
6192 | pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber; | ||
6193 | pCfg->cfghdr.hdr->PageType = pReply->Header.PageType; | ||
6212 | 6194 | ||
6213 | return rc; | 6195 | } |
6214 | } | ||
6215 | 6196 | ||
6216 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 6197 | if (retry_count) |
6217 | /** | 6198 | printk(MYIOC_s_INFO_FMT "Retry completed " |
6218 | * mpt_timer_expired - Callback for timer process. | 6199 | "ret=0x%x timeleft=%ld\n", |
6219 | * Used only internal config functionality. | 6200 | ioc->name, ret, timeleft); |
6220 | * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long | ||
6221 | */ | ||
6222 | static void | ||
6223 | mpt_timer_expired(unsigned long data) | ||
6224 | { | ||
6225 | MPT_ADAPTER *ioc = (MPT_ADAPTER *) data; | ||
6226 | 6201 | ||
6227 | dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_timer_expired! \n", ioc->name)); | 6202 | dcprintk(ioc, printk(KERN_DEBUG "IOCStatus=%04xh, IOCLogInfo=%08xh\n", |
6203 | ret, le32_to_cpu(pReply->IOCLogInfo))); | ||
6228 | 6204 | ||
6229 | /* Perform a FW reload */ | 6205 | out: |
6230 | if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) | ||
6231 | printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name); | ||
6232 | 6206 | ||
6233 | /* No more processing. | 6207 | CLEAR_MGMT_STATUS(ioc->mptbase_cmds.status) |
6234 | * Hard reset clean-up will wake up | 6208 | mutex_unlock(&ioc->mptbase_cmds.mutex); |
6235 | * process and free all resources. | 6209 | if (issue_hard_reset) { |
6236 | */ | 6210 | issue_hard_reset = 0; |
6237 | dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_timer_expired complete!\n", ioc->name)); | 6211 | printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n", |
6212 | ioc->name, __func__); | ||
6213 | mpt_HardResetHandler(ioc, CAN_SLEEP); | ||
6214 | mpt_free_msg_frame(ioc, mf); | ||
6215 | /* attempt one retry for a timed out command */ | ||
6216 | if (!retry_count) { | ||
6217 | printk(MYIOC_s_INFO_FMT | ||
6218 | "Attempting Retry Config request" | ||
6219 | " type 0x%x, page 0x%x," | ||
6220 | " action %d\n", ioc->name, page_type, | ||
6221 | pCfg->cfghdr.hdr->PageNumber, pCfg->action); | ||
6222 | retry_count++; | ||
6223 | goto retry_config; | ||
6224 | } | ||
6225 | } | ||
6226 | return ret; | ||
6238 | 6227 | ||
6239 | return; | ||
6240 | } | 6228 | } |
6241 | 6229 | ||
6242 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 6230 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
@@ -6250,41 +6238,27 @@ mpt_timer_expired(unsigned long data) | |||
6250 | static int | 6238 | static int |
6251 | mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | 6239 | mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) |
6252 | { | 6240 | { |
6253 | CONFIGPARMS *pCfg; | 6241 | switch (reset_phase) { |
6254 | unsigned long flags; | 6242 | case MPT_IOC_SETUP_RESET: |
6255 | 6243 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | |
6256 | dprintk(ioc, printk(MYIOC_s_DEBUG_FMT | 6244 | "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__)); |
6257 | ": IOC %s_reset routed to MPT base driver!\n", | 6245 | break; |
6258 | ioc->name, reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( | 6246 | case MPT_IOC_PRE_RESET: |
6259 | reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); | 6247 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
6260 | 6248 | "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__)); | |
6261 | if (reset_phase == MPT_IOC_SETUP_RESET) { | 6249 | break; |
6262 | ; | 6250 | case MPT_IOC_POST_RESET: |
6263 | } else if (reset_phase == MPT_IOC_PRE_RESET) { | 6251 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
6264 | /* If the internal config Q is not empty - | 6252 | "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__)); |
6265 | * delete timer. MF resources will be freed when | 6253 | /* wake up mptbase_cmds */ |
6266 | * the FIFO's are primed. | 6254 | if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_PENDING) { |
6267 | */ | 6255 | ioc->mptbase_cmds.status |= |
6268 | spin_lock_irqsave(&ioc->FreeQlock, flags); | 6256 | MPT_MGMT_STATUS_DID_IOCRESET; |
6269 | list_for_each_entry(pCfg, &ioc->configQ, linkage) | 6257 | complete(&ioc->mptbase_cmds.done); |
6270 | del_timer(&pCfg->timer); | ||
6271 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
6272 | |||
6273 | } else { | ||
6274 | CONFIGPARMS *pNext; | ||
6275 | |||
6276 | /* Search the configQ for internal commands. | ||
6277 | * Flush the Q, and wake up all suspended threads. | ||
6278 | */ | ||
6279 | spin_lock_irqsave(&ioc->FreeQlock, flags); | ||
6280 | list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) { | ||
6281 | list_del(&pCfg->linkage); | ||
6282 | |||
6283 | pCfg->status = MPT_CONFIG_ERROR; | ||
6284 | pCfg->wait_done = 1; | ||
6285 | wake_up(&mpt_waitq); | ||
6286 | } | 6258 | } |
6287 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | 6259 | break; |
6260 | default: | ||
6261 | break; | ||
6288 | } | 6262 | } |
6289 | 6263 | ||
6290 | return 1; /* currently means nothing really */ | 6264 | return 1; /* currently means nothing really */ |
@@ -7901,7 +7875,7 @@ fusion_init(void) | |||
7901 | /* Register ourselves (mptbase) in order to facilitate | 7875 | /* Register ourselves (mptbase) in order to facilitate |
7902 | * EventNotification handling. | 7876 | * EventNotification handling. |
7903 | */ | 7877 | */ |
7904 | mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER); | 7878 | mpt_base_index = mpt_register(mptbase_reply, MPTBASE_DRIVER); |
7905 | 7879 | ||
7906 | /* Register for hard reset handling callbacks. | 7880 | /* Register for hard reset handling callbacks. |
7907 | */ | 7881 | */ |