diff options
author | Prakash, Sathya <sathya.prakash@lsi.com> | 2008-01-11 04:12:17 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-01-23 12:29:24 -0500 |
commit | 984621b4379cccbd0330e10622021a3cfe464ad5 (patch) | |
tree | 14ae059426f6c0de8f87e15503704c8544d52fe6 /drivers/message/fusion/mptbase.c | |
parent | 32cfe344b002b4d6fe6852a006a9ef3c9ccdb545 (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/mptbase.c')
-rw-r--r-- | drivers/message/fusion/mptbase.c | 94 |
1 files changed, 52 insertions, 42 deletions
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 52fb216dfe74..425f60c21fdd 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 | * |
3051 | void | 3047 | * Return 0 if successfull, or non-zero for failure |
3048 | **/ | ||
3049 | int | ||
3052 | mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size) | 3050 | mpt_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 | **/ |
3073 | void | 3086 | void |
3074 | mpt_free_fw_memory(MPT_ADAPTER *ioc) | 3087 | mpt_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) | |||
3498 | static int | 3507 | static int |
3499 | mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) | 3508 | mpt_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 | } |