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 /drivers/net/cnic.c | |
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>
Diffstat (limited to 'drivers/net/cnic.c')
-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) |