aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion
diff options
context:
space:
mode:
authorPrakash, Sathya <sathya.prakash@lsi.com>2008-01-11 04:12:17 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-01-23 12:29:24 -0500
commit984621b4379cccbd0330e10622021a3cfe464ad5 (patch)
tree14ae059426f6c0de8f87e15503704c8544d52fe6 /drivers/message/fusion
parent32cfe344b002b4d6fe6852a006a9ef3c9ccdb545 (diff)
[SCSI] mpt fusion: Fix for module unload problem in flash less controller environment
This patch fixes the module unload problem in flash less 1030 controller environment where firmware download boot functionality is invoked. The problem is due to the firmware download is being done in the reverse order, which this patch solves by insureing the download occurs to the last controller being reset. signed-off-by: Sathya Prakash <sathya.prakash@lsi.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/message/fusion')
-rw-r--r--drivers/message/fusion/mptbase.c94
-rw-r--r--drivers/message/fusion/mptbase.h2
2 files changed, 53 insertions, 43 deletions
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 52fb216dfe7..425f60c21fd 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -2056,7 +2056,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
2056 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT 2056 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2057 "mpt_upload: alt_%s has cached_fw=%p \n", 2057 "mpt_upload: alt_%s has cached_fw=%p \n",
2058 ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw)); 2058 ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
2059 ioc->alt_ioc->cached_fw = NULL; 2059 ioc->cached_fw = NULL;
2060 } 2060 }
2061 } else { 2061 } else {
2062 printk(MYIOC_s_WARN_FMT 2062 printk(MYIOC_s_WARN_FMT
@@ -2262,10 +2262,12 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
2262 int ret; 2262 int ret;
2263 2263
2264 if (ioc->cached_fw != NULL) { 2264 if (ioc->cached_fw != NULL) {
2265 ddlprintk(ioc, printk(MYIOC_s_INFO_FMT 2265 ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: Pushing FW onto "
2266 "mpt_adapter_disable: Pushing FW onto adapter\n", ioc->name)); 2266 "adapter\n", __FUNCTION__, ioc->name));
2267 if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) { 2267 if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)
2268 printk(MYIOC_s_WARN_FMT "firmware downloadboot failure (%d)!\n", 2268 ioc->cached_fw, CAN_SLEEP)) < 0) {
2269 printk(MYIOC_s_WARN_FMT
2270 ": firmware downloadboot failure (%d)!\n",
2269 ioc->name, ret); 2271 ioc->name, ret);
2270 } 2272 }
2271 } 2273 }
@@ -2303,13 +2305,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
2303 ioc->alloc_total -= sz; 2305 ioc->alloc_total -= sz;
2304 } 2306 }
2305 2307
2306 if (ioc->cached_fw != NULL) { 2308 mpt_free_fw_memory(ioc);
2307 sz = ioc->facts.FWImageSize;
2308 pci_free_consistent(ioc->pcidev, sz,
2309 ioc->cached_fw, ioc->cached_fw_dma);
2310 ioc->cached_fw = NULL;
2311 ioc->alloc_total -= sz;
2312 }
2313 2309
2314 kfree(ioc->spi_data.nvram); 2310 kfree(ioc->spi_data.nvram);
2315 mpt_inactive_raid_list_free(ioc); 2311 mpt_inactive_raid_list_free(ioc);
@@ -3047,44 +3043,62 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
3047 * 3043 *
3048 * If memory has already been allocated, the same (cached) value 3044 * If memory has already been allocated, the same (cached) value
3049 * is returned. 3045 * is returned.
3050 */ 3046 *
3051void 3047 * Return 0 if successfull, or non-zero for failure
3048 **/
3049int
3052mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size) 3050mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
3053{ 3051{
3054 if (ioc->cached_fw) 3052 int rc;
3055 return; /* use already allocated memory */ 3053
3056 if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) { 3054 if (ioc->cached_fw) {
3055 rc = 0; /* use already allocated memory */
3056 goto out;
3057 }
3058 else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
3057 ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */ 3059 ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */
3058 ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma; 3060 ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
3059 ioc->alloc_total += size; 3061 rc = 0;
3060 ioc->alt_ioc->alloc_total -= size; 3062 goto out;
3063 }
3064 ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma);
3065 if (!ioc->cached_fw) {
3066 printk(MYIOC_s_ERR_FMT "Unable to allocate memory for the cached firmware image!\n",
3067 ioc->name);
3068 rc = -1;
3061 } else { 3069 } else {
3062 if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) ) 3070 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FW Image @ %p[%p], sz=%d[%x] bytes\n",
3063 ioc->alloc_total += size; 3071 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, size, size));
3072 ioc->alloc_total += size;
3073 rc = 0;
3064 } 3074 }
3075 out:
3076 return rc;
3065} 3077}
3078
3066/** 3079/**
3067 * mpt_free_fw_memory - free firmware memory 3080 * mpt_free_fw_memory - free firmware memory
3068 * @ioc: Pointer to MPT_ADAPTER structure 3081 * @ioc: Pointer to MPT_ADAPTER structure
3069 * 3082 *
3070 * If alt_img is NULL, delete from ioc structure. 3083 * If alt_img is NULL, delete from ioc structure.
3071 * Else, delete a secondary image in same format. 3084 * Else, delete a secondary image in same format.
3072 */ 3085 **/
3073void 3086void
3074mpt_free_fw_memory(MPT_ADAPTER *ioc) 3087mpt_free_fw_memory(MPT_ADAPTER *ioc)
3075{ 3088{
3076 int sz; 3089 int sz;
3077 3090
3091 if (!ioc->cached_fw)
3092 return;
3093
3078 sz = ioc->facts.FWImageSize; 3094 sz = ioc->facts.FWImageSize;
3079 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n", 3095 dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n",
3080 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz)); 3096 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
3081 pci_free_consistent(ioc->pcidev, sz, ioc->cached_fw, ioc->cached_fw_dma); 3097 pci_free_consistent(ioc->pcidev, sz, ioc->cached_fw, ioc->cached_fw_dma);
3098 ioc->alloc_total -= sz;
3082 ioc->cached_fw = NULL; 3099 ioc->cached_fw = NULL;
3083
3084 return;
3085} 3100}
3086 3101
3087
3088/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 3102/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3089/** 3103/**
3090 * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port. 3104 * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
@@ -3116,17 +3130,12 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
3116 if ((sz = ioc->facts.FWImageSize) == 0) 3130 if ((sz = ioc->facts.FWImageSize) == 0)
3117 return 0; 3131 return 0;
3118 3132
3119 mpt_alloc_fw_memory(ioc, sz); 3133 if (mpt_alloc_fw_memory(ioc, ioc->facts.FWImageSize) != 0)
3134 return -ENOMEM;
3120 3135
3121 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Image @ %p[%p], sz=%d[%x] bytes\n", 3136 dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Image @ %p[%p], sz=%d[%x] bytes\n",
3122 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz)); 3137 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
3123 3138
3124 if (ioc->cached_fw == NULL) {
3125 /* Major Failure.
3126 */
3127 return -ENOMEM;
3128 }
3129
3130 prequest = (sleepFlag == NO_SLEEP) ? kzalloc(ioc->req_sz, GFP_ATOMIC) : 3139 prequest = (sleepFlag == NO_SLEEP) ? kzalloc(ioc->req_sz, GFP_ATOMIC) :
3131 kzalloc(ioc->req_sz, GFP_KERNEL); 3140 kzalloc(ioc->req_sz, GFP_KERNEL);
3132 if (!prequest) { 3141 if (!prequest) {
@@ -3498,12 +3507,12 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3498static int 3507static int
3499mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) 3508mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3500{ 3509{
3501 MPT_ADAPTER *iocp=NULL;
3502 u32 diag0val; 3510 u32 diag0val;
3503 u32 doorbell; 3511 u32 doorbell;
3504 int hard_reset_done = 0; 3512 int hard_reset_done = 0;
3505 int count = 0; 3513 int count = 0;
3506 u32 diag1val = 0; 3514 u32 diag1val = 0;
3515 MpiFwHeader_t *cached_fw; /* Pointer to FW */
3507 3516
3508 /* Clear any existing interrupts */ 3517 /* Clear any existing interrupts */
3509 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); 3518 CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
@@ -3635,22 +3644,24 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3635 } 3644 }
3636 3645
3637 if (ioc->cached_fw) 3646 if (ioc->cached_fw)
3638 iocp = ioc; 3647 cached_fw = (MpiFwHeader_t *)ioc->cached_fw;
3639 else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) 3648 else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
3640 iocp = ioc->alt_ioc; 3649 cached_fw = (MpiFwHeader_t *)ioc->alt_ioc->cached_fw;
3641 if (iocp) { 3650 else
3651 cached_fw = NULL;
3652 if (cached_fw) {
3642 /* If the DownloadBoot operation fails, the 3653 /* If the DownloadBoot operation fails, the
3643 * IOC will be left unusable. This is a fatal error 3654 * IOC will be left unusable. This is a fatal error
3644 * case. _diag_reset will return < 0 3655 * case. _diag_reset will return < 0
3645 */ 3656 */
3646 for (count = 0; count < 30; count ++) { 3657 for (count = 0; count < 30; count ++) {
3647 diag0val = CHIPREG_READ32(&iocp->chip->Diagnostic); 3658 diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3648 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) { 3659 if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3649 break; 3660 break;
3650 } 3661 }
3651 3662
3652 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "cached_fw: diag0val=%x count=%d\n", 3663 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "cached_fw: diag0val=%x count=%d\n",
3653 iocp->name, diag0val, count)); 3664 ioc->name, diag0val, count));
3654 /* wait 1 sec */ 3665 /* wait 1 sec */
3655 if (sleepFlag == CAN_SLEEP) { 3666 if (sleepFlag == CAN_SLEEP) {
3656 msleep (1000); 3667 msleep (1000);
@@ -3658,8 +3669,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3658 mdelay (1000); 3669 mdelay (1000);
3659 } 3670 }
3660 } 3671 }
3661 if ((count = mpt_downloadboot(ioc, 3672 if ((count = mpt_downloadboot(ioc, cached_fw, sleepFlag)) < 0) {
3662 (MpiFwHeader_t *)iocp->cached_fw, sleepFlag)) < 0) {
3663 printk(MYIOC_s_WARN_FMT 3673 printk(MYIOC_s_WARN_FMT
3664 "firmware downloadboot failure (%d)!\n", ioc->name, count); 3674 "firmware downloadboot failure (%d)!\n", ioc->name, count);
3665 } 3675 }
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index d7682e083f5..b49b706c002 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -907,7 +907,7 @@ extern u32 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked);
907extern void mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buf, int *size, int len, int showlan); 907extern void mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buf, int *size, int len, int showlan);
908extern int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag); 908extern int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
909extern int mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *cfg); 909extern int mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *cfg);
910extern void mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size); 910extern int mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size);
911extern void mpt_free_fw_memory(MPT_ADAPTER *ioc); 911extern void mpt_free_fw_memory(MPT_ADAPTER *ioc);
912extern int mpt_findImVolumes(MPT_ADAPTER *ioc); 912extern int mpt_findImVolumes(MPT_ADAPTER *ioc);
913extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); 913extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);