diff options
| author | Michael Chan <mchan@broadcom.com> | 2010-06-24 10:58:40 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2010-06-25 23:37:20 -0400 |
| commit | 644b9d4f8b8d74f4d87f14dede5e331555d3e701 (patch) | |
| tree | b490000b7e9f80e2914abe926c3877f68e81a291 | |
| parent | e6c2889478f04b30e5a71d753734644c579472fa (diff) | |
cnic: Restructure kcq processing.
By doing more work in the common function cnic_get_kcqes(), and
making full use of the kcq_info structure.
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/cnic.c | 76 |
1 files changed, 22 insertions, 54 deletions
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index c1f0d16dd47a..fabdb7868c94 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c | |||
| @@ -2141,18 +2141,20 @@ static u16 cnic_bnx2x_hw_idx(u16 idx) | |||
| 2141 | return idx; | 2141 | return idx; |
| 2142 | } | 2142 | } |
| 2143 | 2143 | ||
| 2144 | static int cnic_get_kcqes(struct cnic_dev *dev, u16 hw_prod, u16 *sw_prod) | 2144 | static int cnic_get_kcqes(struct cnic_dev *dev, struct kcq_info *info) |
| 2145 | { | 2145 | { |
| 2146 | struct cnic_local *cp = dev->cnic_priv; | 2146 | struct cnic_local *cp = dev->cnic_priv; |
| 2147 | u16 i, ri, last; | 2147 | u16 i, ri, hw_prod, last; |
| 2148 | struct kcqe *kcqe; | 2148 | struct kcqe *kcqe; |
| 2149 | int kcqe_cnt = 0, last_cnt = 0; | 2149 | int kcqe_cnt = 0, last_cnt = 0; |
| 2150 | 2150 | ||
| 2151 | i = ri = last = *sw_prod; | 2151 | i = ri = last = info->sw_prod_idx; |
| 2152 | ri &= MAX_KCQ_IDX; | 2152 | ri &= MAX_KCQ_IDX; |
| 2153 | hw_prod = *info->hw_prod_idx_ptr; | ||
| 2154 | hw_prod = cp->hw_idx(hw_prod); | ||
| 2153 | 2155 | ||
| 2154 | while ((i != hw_prod) && (kcqe_cnt < MAX_COMPLETED_KCQE)) { | 2156 | while ((i != hw_prod) && (kcqe_cnt < MAX_COMPLETED_KCQE)) { |
| 2155 | kcqe = &cp->kcq1.kcq[KCQ_PG(ri)][KCQ_IDX(ri)]; | 2157 | kcqe = &info->kcq[KCQ_PG(ri)][KCQ_IDX(ri)]; |
| 2156 | cp->completed_kcq[kcqe_cnt++] = kcqe; | 2158 | cp->completed_kcq[kcqe_cnt++] = kcqe; |
| 2157 | i = cp->next_idx(i); | 2159 | i = cp->next_idx(i); |
| 2158 | ri = i & MAX_KCQ_IDX; | 2160 | ri = i & MAX_KCQ_IDX; |
| @@ -2162,7 +2164,7 @@ static int cnic_get_kcqes(struct cnic_dev *dev, u16 hw_prod, u16 *sw_prod) | |||
| 2162 | } | 2164 | } |
| 2163 | } | 2165 | } |
| 2164 | 2166 | ||
| 2165 | *sw_prod = last; | 2167 | info->sw_prod_idx = last; |
| 2166 | return last_cnt; | 2168 | return last_cnt; |
| 2167 | } | 2169 | } |
| 2168 | 2170 | ||
| @@ -2224,10 +2226,8 @@ static void cnic_chk_pkt_rings(struct cnic_local *cp) | |||
| 2224 | static int cnic_service_bnx2(void *data, void *status_blk) | 2226 | static int cnic_service_bnx2(void *data, void *status_blk) |
| 2225 | { | 2227 | { |
| 2226 | struct cnic_dev *dev = data; | 2228 | struct cnic_dev *dev = data; |
| 2227 | struct status_block *sblk = status_blk; | ||
| 2228 | struct cnic_local *cp = dev->cnic_priv; | 2229 | struct cnic_local *cp = dev->cnic_priv; |
| 2229 | u32 status_idx = sblk->status_idx; | 2230 | u32 status_idx = *cp->kcq1.status_idx_ptr; |
| 2230 | u16 hw_prod, sw_prod; | ||
| 2231 | int kcqe_cnt; | 2231 | int kcqe_cnt; |
| 2232 | 2232 | ||
| 2233 | if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags))) | 2233 | if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags))) |
| @@ -2235,29 +2235,20 @@ static int cnic_service_bnx2(void *data, void *status_blk) | |||
| 2235 | 2235 | ||
| 2236 | cp->kwq_con_idx = *cp->kwq_con_idx_ptr; | 2236 | cp->kwq_con_idx = *cp->kwq_con_idx_ptr; |
| 2237 | 2237 | ||
| 2238 | hw_prod = sblk->status_completion_producer_index; | 2238 | while ((kcqe_cnt = cnic_get_kcqes(dev, &cp->kcq1))) { |
| 2239 | sw_prod = cp->kcq1.sw_prod_idx; | ||
| 2240 | while (sw_prod != hw_prod) { | ||
| 2241 | kcqe_cnt = cnic_get_kcqes(dev, hw_prod, &sw_prod); | ||
| 2242 | if (kcqe_cnt == 0) | ||
| 2243 | goto done; | ||
| 2244 | 2239 | ||
| 2245 | service_kcqes(dev, kcqe_cnt); | 2240 | service_kcqes(dev, kcqe_cnt); |
| 2246 | 2241 | ||
| 2247 | /* Tell compiler that status_blk fields can change. */ | 2242 | /* Tell compiler that status_blk fields can change. */ |
| 2248 | barrier(); | 2243 | barrier(); |
| 2249 | if (status_idx != sblk->status_idx) { | 2244 | if (status_idx != *cp->kcq1.status_idx_ptr) { |
| 2250 | status_idx = sblk->status_idx; | 2245 | status_idx = *cp->kcq1.status_idx_ptr; |
| 2251 | cp->kwq_con_idx = *cp->kwq_con_idx_ptr; | 2246 | cp->kwq_con_idx = *cp->kwq_con_idx_ptr; |
| 2252 | hw_prod = sblk->status_completion_producer_index; | ||
| 2253 | } else | 2247 | } else |
| 2254 | break; | 2248 | break; |
| 2255 | } | 2249 | } |
| 2256 | 2250 | ||
| 2257 | done: | 2251 | CNIC_WR16(dev, cp->kcq1.io_addr, cp->kcq1.sw_prod_idx); |
| 2258 | CNIC_WR16(dev, cp->kcq1.io_addr, sw_prod); | ||
| 2259 | |||
| 2260 | cp->kcq1.sw_prod_idx = sw_prod; | ||
| 2261 | 2252 | ||
| 2262 | cnic_chk_pkt_rings(cp); | 2253 | cnic_chk_pkt_rings(cp); |
| 2263 | return status_idx; | 2254 | return status_idx; |
| @@ -2268,34 +2259,25 @@ static void cnic_service_bnx2_msix(unsigned long data) | |||
| 2268 | struct cnic_dev *dev = (struct cnic_dev *) data; | 2259 | struct cnic_dev *dev = (struct cnic_dev *) data; |
| 2269 | struct cnic_local *cp = dev->cnic_priv; | 2260 | struct cnic_local *cp = dev->cnic_priv; |
| 2270 | struct status_block_msix *status_blk = cp->status_blk.bnx2; | 2261 | struct status_block_msix *status_blk = cp->status_blk.bnx2; |
| 2271 | u32 status_idx = status_blk->status_idx; | 2262 | u32 status_idx = *cp->kcq1.status_idx_ptr; |
| 2272 | u16 hw_prod, sw_prod; | ||
| 2273 | int kcqe_cnt; | 2263 | int kcqe_cnt; |
| 2274 | 2264 | ||
| 2275 | cp->kwq_con_idx = status_blk->status_cmd_consumer_index; | 2265 | cp->kwq_con_idx = status_blk->status_cmd_consumer_index; |
| 2276 | 2266 | ||
| 2277 | hw_prod = status_blk->status_completion_producer_index; | 2267 | while ((kcqe_cnt = cnic_get_kcqes(dev, &cp->kcq1))) { |
| 2278 | sw_prod = cp->kcq1.sw_prod_idx; | ||
| 2279 | while (sw_prod != hw_prod) { | ||
| 2280 | kcqe_cnt = cnic_get_kcqes(dev, hw_prod, &sw_prod); | ||
| 2281 | if (kcqe_cnt == 0) | ||
| 2282 | goto done; | ||
| 2283 | 2268 | ||
| 2284 | service_kcqes(dev, kcqe_cnt); | 2269 | service_kcqes(dev, kcqe_cnt); |
| 2285 | 2270 | ||
| 2286 | /* Tell compiler that status_blk fields can change. */ | 2271 | /* Tell compiler that status_blk fields can change. */ |
| 2287 | barrier(); | 2272 | barrier(); |
| 2288 | if (status_idx != status_blk->status_idx) { | 2273 | if (status_idx != *cp->kcq1.status_idx_ptr) { |
| 2289 | status_idx = status_blk->status_idx; | 2274 | status_idx = *cp->kcq1.status_idx_ptr; |
| 2290 | cp->kwq_con_idx = status_blk->status_cmd_consumer_index; | 2275 | cp->kwq_con_idx = status_blk->status_cmd_consumer_index; |
| 2291 | hw_prod = status_blk->status_completion_producer_index; | ||
| 2292 | } else | 2276 | } else |
| 2293 | break; | 2277 | break; |
| 2294 | } | 2278 | } |
| 2295 | 2279 | ||
| 2296 | done: | 2280 | CNIC_WR16(dev, cp->kcq1.io_addr, cp->kcq1.sw_prod_idx); |
| 2297 | CNIC_WR16(dev, cp->kcq1.io_addr, sw_prod); | ||
| 2298 | cp->kcq1.sw_prod_idx = sw_prod; | ||
| 2299 | 2281 | ||
| 2300 | cnic_chk_pkt_rings(cp); | 2282 | cnic_chk_pkt_rings(cp); |
| 2301 | 2283 | ||
| @@ -2360,41 +2342,27 @@ static void cnic_service_bnx2x_bh(unsigned long data) | |||
| 2360 | { | 2342 | { |
| 2361 | struct cnic_dev *dev = (struct cnic_dev *) data; | 2343 | struct cnic_dev *dev = (struct cnic_dev *) data; |
| 2362 | struct cnic_local *cp = dev->cnic_priv; | 2344 | struct cnic_local *cp = dev->cnic_priv; |
| 2363 | u16 hw_prod, sw_prod; | 2345 | u32 status_idx = *cp->kcq1.status_idx_ptr; |
| 2364 | struct cstorm_status_block_c *sblk = | ||
| 2365 | &cp->status_blk.bnx2x->c_status_block; | ||
| 2366 | u32 status_idx = sblk->status_block_index; | ||
| 2367 | int kcqe_cnt; | 2346 | int kcqe_cnt; |
| 2368 | 2347 | ||
| 2369 | if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags))) | 2348 | if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags))) |
| 2370 | return; | 2349 | return; |
| 2371 | 2350 | ||
| 2372 | hw_prod = sblk->index_values[HC_INDEX_C_ISCSI_EQ_CONS]; | 2351 | while ((kcqe_cnt = cnic_get_kcqes(dev, &cp->kcq1))) { |
| 2373 | hw_prod = cp->hw_idx(hw_prod); | ||
| 2374 | sw_prod = cp->kcq1.sw_prod_idx; | ||
| 2375 | while (sw_prod != hw_prod) { | ||
| 2376 | kcqe_cnt = cnic_get_kcqes(dev, hw_prod, &sw_prod); | ||
| 2377 | if (kcqe_cnt == 0) | ||
| 2378 | goto done; | ||
| 2379 | 2352 | ||
| 2380 | service_kcqes(dev, kcqe_cnt); | 2353 | service_kcqes(dev, kcqe_cnt); |
| 2381 | 2354 | ||
| 2382 | /* Tell compiler that sblk fields can change. */ | 2355 | /* Tell compiler that sblk fields can change. */ |
| 2383 | barrier(); | 2356 | barrier(); |
| 2384 | if (status_idx == sblk->status_block_index) | 2357 | if (status_idx == *cp->kcq1.status_idx_ptr) |
| 2385 | break; | 2358 | break; |
| 2386 | 2359 | ||
| 2387 | status_idx = sblk->status_block_index; | 2360 | status_idx = *cp->kcq1.status_idx_ptr; |
| 2388 | hw_prod = sblk->index_values[HC_INDEX_C_ISCSI_EQ_CONS]; | ||
| 2389 | hw_prod = cp->hw_idx(hw_prod); | ||
| 2390 | } | 2361 | } |
| 2391 | 2362 | ||
| 2392 | done: | 2363 | CNIC_WR16(dev, cp->kcq1.io_addr, cp->kcq1.sw_prod_idx + MAX_KCQ_IDX); |
| 2393 | CNIC_WR16(dev, cp->kcq1.io_addr, sw_prod + MAX_KCQ_IDX); | ||
| 2394 | cnic_ack_bnx2x_int(dev, cp->status_blk_num, CSTORM_ID, | 2364 | cnic_ack_bnx2x_int(dev, cp->status_blk_num, CSTORM_ID, |
| 2395 | status_idx, IGU_INT_ENABLE, 1); | 2365 | status_idx, IGU_INT_ENABLE, 1); |
| 2396 | |||
| 2397 | cp->kcq1.sw_prod_idx = sw_prod; | ||
| 2398 | } | 2366 | } |
| 2399 | 2367 | ||
| 2400 | static int cnic_service_bnx2x(void *data, void *status_blk) | 2368 | static int cnic_service_bnx2x(void *data, void *status_blk) |
