diff options
author | Andrew Vasquez <andrew.vasquez@qlogic.com> | 2008-01-31 15:33:48 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-02-07 19:02:39 -0500 |
commit | e87110852d0bd331d50c3de686a7fc9626579d60 (patch) | |
tree | 9501f4a06588c14029c6e2487cfdfa0fb710f82e /drivers/scsi | |
parent | 0afb467b4757adb9c6e3817f2e752d658a494352 (diff) |
[SCSI] qla2xxx: Cleanse memory allocation logic during probe.
- Drop loop-till-allocated structure of code within
qla2x00_mem_alloc().
- Properly unwind deallcations of memory during failures.
- Drop qla2x00_allocate_sp_pool() and qla2x00_free_sp_pool()
functions as their implementations can easily be collapsed into
the callers.
- Defer DMA pool allocation of SFP data until requested.
Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 13 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 328 |
2 files changed, 111 insertions, 230 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index adf97320574b..1dd8591bd5c2 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -428,6 +428,19 @@ qla2x00_sysfs_read_sfp(struct kobject *kobj, | |||
428 | if (!capable(CAP_SYS_ADMIN) || off != 0 || count != SFP_DEV_SIZE * 2) | 428 | if (!capable(CAP_SYS_ADMIN) || off != 0 || count != SFP_DEV_SIZE * 2) |
429 | return 0; | 429 | return 0; |
430 | 430 | ||
431 | if (ha->sfp_data) | ||
432 | goto do_read; | ||
433 | |||
434 | ha->sfp_data = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, | ||
435 | &ha->sfp_data_dma); | ||
436 | if (!ha->sfp_data) { | ||
437 | qla_printk(KERN_WARNING, ha, | ||
438 | "Unable to allocate memory for SFP read-data.\n"); | ||
439 | return 0; | ||
440 | } | ||
441 | |||
442 | do_read: | ||
443 | memset(ha->sfp_data, 0, SFP_BLOCK_SIZE); | ||
431 | addr = 0xa0; | 444 | addr = 0xa0; |
432 | for (iter = 0, offset = 0; iter < (SFP_DEV_SIZE * 2) / SFP_BLOCK_SIZE; | 445 | for (iter = 0, offset = 0; iter < (SFP_DEV_SIZE * 2) / SFP_BLOCK_SIZE; |
433 | iter++, offset += SFP_BLOCK_SIZE) { | 446 | iter++, offset += SFP_BLOCK_SIZE) { |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 3869e4d174c6..7f78e9400523 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -204,10 +204,8 @@ static int qla2x00_do_dpc(void *data); | |||
204 | 204 | ||
205 | static void qla2x00_rst_aen(scsi_qla_host_t *); | 205 | static void qla2x00_rst_aen(scsi_qla_host_t *); |
206 | 206 | ||
207 | static uint8_t qla2x00_mem_alloc(scsi_qla_host_t *); | 207 | static int qla2x00_mem_alloc(scsi_qla_host_t *); |
208 | static void qla2x00_mem_free(scsi_qla_host_t *ha); | 208 | static void qla2x00_mem_free(scsi_qla_host_t *ha); |
209 | static int qla2x00_allocate_sp_pool( scsi_qla_host_t *ha); | ||
210 | static void qla2x00_free_sp_pool(scsi_qla_host_t *ha); | ||
211 | static void qla2x00_sp_free_dma(scsi_qla_host_t *, srb_t *); | 209 | static void qla2x00_sp_free_dma(scsi_qla_host_t *, srb_t *); |
212 | 210 | ||
213 | /* -------------------------------------------------------------------------- */ | 211 | /* -------------------------------------------------------------------------- */ |
@@ -2032,196 +2030,109 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer) | |||
2032 | * | 2030 | * |
2033 | * Returns: | 2031 | * Returns: |
2034 | * 0 = success. | 2032 | * 0 = success. |
2035 | * 1 = failure. | 2033 | * !0 = failure. |
2036 | */ | 2034 | */ |
2037 | static uint8_t | 2035 | static int |
2038 | qla2x00_mem_alloc(scsi_qla_host_t *ha) | 2036 | qla2x00_mem_alloc(scsi_qla_host_t *ha) |
2039 | { | 2037 | { |
2040 | char name[16]; | 2038 | char name[16]; |
2041 | uint8_t status = 1; | ||
2042 | int retry= 10; | ||
2043 | |||
2044 | do { | ||
2045 | /* | ||
2046 | * This will loop only once if everything goes well, else some | ||
2047 | * number of retries will be performed to get around a kernel | ||
2048 | * bug where available mem is not allocated until after a | ||
2049 | * little delay and a retry. | ||
2050 | */ | ||
2051 | ha->request_ring = dma_alloc_coherent(&ha->pdev->dev, | ||
2052 | (ha->request_q_length + 1) * sizeof(request_t), | ||
2053 | &ha->request_dma, GFP_KERNEL); | ||
2054 | if (ha->request_ring == NULL) { | ||
2055 | qla_printk(KERN_WARNING, ha, | ||
2056 | "Memory Allocation failed - request_ring\n"); | ||
2057 | |||
2058 | qla2x00_mem_free(ha); | ||
2059 | msleep(100); | ||
2060 | |||
2061 | continue; | ||
2062 | } | ||
2063 | |||
2064 | ha->response_ring = dma_alloc_coherent(&ha->pdev->dev, | ||
2065 | (ha->response_q_length + 1) * sizeof(response_t), | ||
2066 | &ha->response_dma, GFP_KERNEL); | ||
2067 | if (ha->response_ring == NULL) { | ||
2068 | qla_printk(KERN_WARNING, ha, | ||
2069 | "Memory Allocation failed - response_ring\n"); | ||
2070 | |||
2071 | qla2x00_mem_free(ha); | ||
2072 | msleep(100); | ||
2073 | |||
2074 | continue; | ||
2075 | } | ||
2076 | |||
2077 | ha->gid_list = dma_alloc_coherent(&ha->pdev->dev, GID_LIST_SIZE, | ||
2078 | &ha->gid_list_dma, GFP_KERNEL); | ||
2079 | if (ha->gid_list == NULL) { | ||
2080 | qla_printk(KERN_WARNING, ha, | ||
2081 | "Memory Allocation failed - gid_list\n"); | ||
2082 | |||
2083 | qla2x00_mem_free(ha); | ||
2084 | msleep(100); | ||
2085 | |||
2086 | continue; | ||
2087 | } | ||
2088 | |||
2089 | /* get consistent memory allocated for init control block */ | ||
2090 | ha->init_cb = dma_alloc_coherent(&ha->pdev->dev, | ||
2091 | ha->init_cb_size, &ha->init_cb_dma, GFP_KERNEL); | ||
2092 | if (ha->init_cb == NULL) { | ||
2093 | qla_printk(KERN_WARNING, ha, | ||
2094 | "Memory Allocation failed - init_cb\n"); | ||
2095 | |||
2096 | qla2x00_mem_free(ha); | ||
2097 | msleep(100); | ||
2098 | |||
2099 | continue; | ||
2100 | } | ||
2101 | memset(ha->init_cb, 0, ha->init_cb_size); | ||
2102 | |||
2103 | snprintf(name, sizeof(name), "%s_%ld", QLA2XXX_DRIVER_NAME, | ||
2104 | ha->host_no); | ||
2105 | ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev, | ||
2106 | DMA_POOL_SIZE, 8, 0); | ||
2107 | if (ha->s_dma_pool == NULL) { | ||
2108 | qla_printk(KERN_WARNING, ha, | ||
2109 | "Memory Allocation failed - s_dma_pool\n"); | ||
2110 | |||
2111 | qla2x00_mem_free(ha); | ||
2112 | msleep(100); | ||
2113 | |||
2114 | continue; | ||
2115 | } | ||
2116 | |||
2117 | if (qla2x00_allocate_sp_pool(ha)) { | ||
2118 | qla_printk(KERN_WARNING, ha, | ||
2119 | "Memory Allocation failed - " | ||
2120 | "qla2x00_allocate_sp_pool()\n"); | ||
2121 | |||
2122 | qla2x00_mem_free(ha); | ||
2123 | msleep(100); | ||
2124 | |||
2125 | continue; | ||
2126 | } | ||
2127 | |||
2128 | /* Allocate memory for SNS commands */ | ||
2129 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) { | ||
2130 | /* Get consistent memory allocated for SNS commands */ | ||
2131 | ha->sns_cmd = dma_alloc_coherent(&ha->pdev->dev, | ||
2132 | sizeof(struct sns_cmd_pkt), &ha->sns_cmd_dma, | ||
2133 | GFP_KERNEL); | ||
2134 | if (ha->sns_cmd == NULL) { | ||
2135 | /* error */ | ||
2136 | qla_printk(KERN_WARNING, ha, | ||
2137 | "Memory Allocation failed - sns_cmd\n"); | ||
2138 | |||
2139 | qla2x00_mem_free(ha); | ||
2140 | msleep(100); | ||
2141 | |||
2142 | continue; | ||
2143 | } | ||
2144 | memset(ha->sns_cmd, 0, sizeof(struct sns_cmd_pkt)); | ||
2145 | } else { | ||
2146 | /* Get consistent memory allocated for MS IOCB */ | ||
2147 | ha->ms_iocb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, | ||
2148 | &ha->ms_iocb_dma); | ||
2149 | if (ha->ms_iocb == NULL) { | ||
2150 | /* error */ | ||
2151 | qla_printk(KERN_WARNING, ha, | ||
2152 | "Memory Allocation failed - ms_iocb\n"); | ||
2153 | |||
2154 | qla2x00_mem_free(ha); | ||
2155 | msleep(100); | ||
2156 | |||
2157 | continue; | ||
2158 | } | ||
2159 | memset(ha->ms_iocb, 0, sizeof(ms_iocb_entry_t)); | ||
2160 | |||
2161 | /* | ||
2162 | * Get consistent memory allocated for CT SNS | ||
2163 | * commands | ||
2164 | */ | ||
2165 | ha->ct_sns = dma_alloc_coherent(&ha->pdev->dev, | ||
2166 | sizeof(struct ct_sns_pkt), &ha->ct_sns_dma, | ||
2167 | GFP_KERNEL); | ||
2168 | if (ha->ct_sns == NULL) { | ||
2169 | /* error */ | ||
2170 | qla_printk(KERN_WARNING, ha, | ||
2171 | "Memory Allocation failed - ct_sns\n"); | ||
2172 | |||
2173 | qla2x00_mem_free(ha); | ||
2174 | msleep(100); | ||
2175 | |||
2176 | continue; | ||
2177 | } | ||
2178 | memset(ha->ct_sns, 0, sizeof(struct ct_sns_pkt)); | ||
2179 | |||
2180 | if (IS_FWI2_CAPABLE(ha)) { | ||
2181 | /* | ||
2182 | * Get consistent memory allocated for SFP | ||
2183 | * block. | ||
2184 | */ | ||
2185 | ha->sfp_data = dma_pool_alloc(ha->s_dma_pool, | ||
2186 | GFP_KERNEL, &ha->sfp_data_dma); | ||
2187 | if (ha->sfp_data == NULL) { | ||
2188 | qla_printk(KERN_WARNING, ha, | ||
2189 | "Memory Allocation failed - " | ||
2190 | "sfp_data\n"); | ||
2191 | |||
2192 | qla2x00_mem_free(ha); | ||
2193 | msleep(100); | ||
2194 | |||
2195 | continue; | ||
2196 | } | ||
2197 | memset(ha->sfp_data, 0, SFP_BLOCK_SIZE); | ||
2198 | } | ||
2199 | } | ||
2200 | |||
2201 | /* Get memory for cached NVRAM */ | ||
2202 | ha->nvram = kzalloc(MAX_NVRAM_SIZE, GFP_KERNEL); | ||
2203 | if (ha->nvram == NULL) { | ||
2204 | /* error */ | ||
2205 | qla_printk(KERN_WARNING, ha, | ||
2206 | "Memory Allocation failed - nvram cache\n"); | ||
2207 | |||
2208 | qla2x00_mem_free(ha); | ||
2209 | msleep(100); | ||
2210 | |||
2211 | continue; | ||
2212 | } | ||
2213 | 2039 | ||
2214 | /* Done all allocations without any error. */ | 2040 | ha->request_ring = dma_alloc_coherent(&ha->pdev->dev, |
2215 | status = 0; | 2041 | (ha->request_q_length + 1) * sizeof(request_t), &ha->request_dma, |
2042 | GFP_KERNEL); | ||
2043 | if (!ha->request_ring) | ||
2044 | goto fail; | ||
2045 | |||
2046 | ha->response_ring = dma_alloc_coherent(&ha->pdev->dev, | ||
2047 | (ha->response_q_length + 1) * sizeof(response_t), | ||
2048 | &ha->response_dma, GFP_KERNEL); | ||
2049 | if (!ha->response_ring) | ||
2050 | goto fail_free_request_ring; | ||
2051 | |||
2052 | ha->gid_list = dma_alloc_coherent(&ha->pdev->dev, GID_LIST_SIZE, | ||
2053 | &ha->gid_list_dma, GFP_KERNEL); | ||
2054 | if (!ha->gid_list) | ||
2055 | goto fail_free_response_ring; | ||
2056 | |||
2057 | ha->init_cb = dma_alloc_coherent(&ha->pdev->dev, ha->init_cb_size, | ||
2058 | &ha->init_cb_dma, GFP_KERNEL); | ||
2059 | if (!ha->init_cb) | ||
2060 | goto fail_free_gid_list; | ||
2061 | |||
2062 | snprintf(name, sizeof(name), "%s_%ld", QLA2XXX_DRIVER_NAME, | ||
2063 | ha->host_no); | ||
2064 | ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev, | ||
2065 | DMA_POOL_SIZE, 8, 0); | ||
2066 | if (!ha->s_dma_pool) | ||
2067 | goto fail_free_init_cb; | ||
2216 | 2068 | ||
2217 | } while (retry-- && status != 0); | 2069 | ha->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep); |
2070 | if (!ha->srb_mempool) | ||
2071 | goto fail_free_s_dma_pool; | ||
2072 | |||
2073 | /* Get memory for cached NVRAM */ | ||
2074 | ha->nvram = kzalloc(MAX_NVRAM_SIZE, GFP_KERNEL); | ||
2075 | if (!ha->nvram) | ||
2076 | goto fail_free_srb_mempool; | ||
2077 | |||
2078 | /* Allocate memory for SNS commands */ | ||
2079 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) { | ||
2080 | /* Get consistent memory allocated for SNS commands */ | ||
2081 | ha->sns_cmd = dma_alloc_coherent(&ha->pdev->dev, | ||
2082 | sizeof(struct sns_cmd_pkt), &ha->sns_cmd_dma, GFP_KERNEL); | ||
2083 | if (!ha->sns_cmd) | ||
2084 | goto fail_free_nvram; | ||
2085 | } else { | ||
2086 | /* Get consistent memory allocated for MS IOCB */ | ||
2087 | ha->ms_iocb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, | ||
2088 | &ha->ms_iocb_dma); | ||
2089 | if (!ha->ms_iocb) | ||
2090 | goto fail_free_nvram; | ||
2218 | 2091 | ||
2219 | if (status) { | 2092 | /* Get consistent memory allocated for CT SNS commands */ |
2220 | printk(KERN_WARNING | 2093 | ha->ct_sns = dma_alloc_coherent(&ha->pdev->dev, |
2221 | "%s(): **** FAILED ****\n", __func__); | 2094 | sizeof(struct ct_sns_pkt), &ha->ct_sns_dma, GFP_KERNEL); |
2095 | if (!ha->ct_sns) | ||
2096 | goto fail_free_ms_iocb; | ||
2222 | } | 2097 | } |
2223 | 2098 | ||
2224 | return(status); | 2099 | return 0; |
2100 | |||
2101 | fail_free_ms_iocb: | ||
2102 | dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma); | ||
2103 | ha->ms_iocb = NULL; | ||
2104 | ha->ms_iocb_dma = 0; | ||
2105 | fail_free_nvram: | ||
2106 | kfree(ha->nvram); | ||
2107 | ha->nvram = NULL; | ||
2108 | fail_free_srb_mempool: | ||
2109 | mempool_destroy(ha->srb_mempool); | ||
2110 | ha->srb_mempool = NULL; | ||
2111 | fail_free_s_dma_pool: | ||
2112 | dma_pool_destroy(ha->s_dma_pool); | ||
2113 | ha->s_dma_pool = NULL; | ||
2114 | fail_free_init_cb: | ||
2115 | dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, ha->init_cb, | ||
2116 | ha->init_cb_dma); | ||
2117 | ha->init_cb = NULL; | ||
2118 | ha->init_cb_dma = 0; | ||
2119 | fail_free_gid_list: | ||
2120 | dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, ha->gid_list, | ||
2121 | ha->gid_list_dma); | ||
2122 | ha->gid_list = NULL; | ||
2123 | ha->gid_list_dma = 0; | ||
2124 | fail_free_response_ring: | ||
2125 | dma_free_coherent(&ha->pdev->dev, (ha->response_q_length + 1) * | ||
2126 | sizeof(response_t), ha->response_ring, ha->response_dma); | ||
2127 | ha->response_ring = NULL; | ||
2128 | ha->response_dma = 0; | ||
2129 | fail_free_request_ring: | ||
2130 | dma_free_coherent(&ha->pdev->dev, (ha->request_q_length + 1) * | ||
2131 | sizeof(request_t), ha->request_ring, ha->request_dma); | ||
2132 | ha->request_ring = NULL; | ||
2133 | ha->request_dma = 0; | ||
2134 | fail: | ||
2135 | return -ENOMEM; | ||
2225 | } | 2136 | } |
2226 | 2137 | ||
2227 | /* | 2138 | /* |
@@ -2237,14 +2148,8 @@ qla2x00_mem_free(scsi_qla_host_t *ha) | |||
2237 | struct list_head *fcpl, *fcptemp; | 2148 | struct list_head *fcpl, *fcptemp; |
2238 | fc_port_t *fcport; | 2149 | fc_port_t *fcport; |
2239 | 2150 | ||
2240 | if (ha == NULL) { | 2151 | if (ha->srb_mempool) |
2241 | /* error */ | 2152 | mempool_destroy(ha->srb_mempool); |
2242 | DEBUG2(printk("%s(): ERROR invalid ha pointer.\n", __func__)); | ||
2243 | return; | ||
2244 | } | ||
2245 | |||
2246 | /* free sp pool */ | ||
2247 | qla2x00_free_sp_pool(ha); | ||
2248 | 2153 | ||
2249 | if (ha->fce) | 2154 | if (ha->fce) |
2250 | dma_free_coherent(&ha->pdev->dev, FCE_SIZE, ha->fce, | 2155 | dma_free_coherent(&ha->pdev->dev, FCE_SIZE, ha->fce, |
@@ -2292,6 +2197,7 @@ qla2x00_mem_free(scsi_qla_host_t *ha) | |||
2292 | (ha->request_q_length + 1) * sizeof(request_t), | 2197 | (ha->request_q_length + 1) * sizeof(request_t), |
2293 | ha->request_ring, ha->request_dma); | 2198 | ha->request_ring, ha->request_dma); |
2294 | 2199 | ||
2200 | ha->srb_mempool = NULL; | ||
2295 | ha->eft = NULL; | 2201 | ha->eft = NULL; |
2296 | ha->eft_dma = 0; | 2202 | ha->eft_dma = 0; |
2297 | ha->sns_cmd = NULL; | 2203 | ha->sns_cmd = NULL; |
@@ -2330,44 +2236,6 @@ qla2x00_mem_free(scsi_qla_host_t *ha) | |||
2330 | kfree(ha->nvram); | 2236 | kfree(ha->nvram); |
2331 | } | 2237 | } |
2332 | 2238 | ||
2333 | /* | ||
2334 | * qla2x00_allocate_sp_pool | ||
2335 | * This routine is called during initialization to allocate | ||
2336 | * memory for local srb_t. | ||
2337 | * | ||
2338 | * Input: | ||
2339 | * ha = adapter block pointer. | ||
2340 | * | ||
2341 | * Context: | ||
2342 | * Kernel context. | ||
2343 | */ | ||
2344 | static int | ||
2345 | qla2x00_allocate_sp_pool(scsi_qla_host_t *ha) | ||
2346 | { | ||
2347 | int rval; | ||
2348 | |||
2349 | rval = QLA_SUCCESS; | ||
2350 | ha->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep); | ||
2351 | if (ha->srb_mempool == NULL) { | ||
2352 | qla_printk(KERN_INFO, ha, "Unable to allocate SRB mempool.\n"); | ||
2353 | rval = QLA_FUNCTION_FAILED; | ||
2354 | } | ||
2355 | return (rval); | ||
2356 | } | ||
2357 | |||
2358 | /* | ||
2359 | * This routine frees all adapter allocated memory. | ||
2360 | * | ||
2361 | */ | ||
2362 | static void | ||
2363 | qla2x00_free_sp_pool( scsi_qla_host_t *ha) | ||
2364 | { | ||
2365 | if (ha->srb_mempool) { | ||
2366 | mempool_destroy(ha->srb_mempool); | ||
2367 | ha->srb_mempool = NULL; | ||
2368 | } | ||
2369 | } | ||
2370 | |||
2371 | /************************************************************************** | 2239 | /************************************************************************** |
2372 | * qla2x00_do_dpc | 2240 | * qla2x00_do_dpc |
2373 | * This kernel thread is a task that is schedule by the interrupt handler | 2241 | * This kernel thread is a task that is schedule by the interrupt handler |