diff options
Diffstat (limited to 'drivers/net/cnic.c')
-rw-r--r-- | drivers/net/cnic.c | 80 |
1 files changed, 73 insertions, 7 deletions
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 4b451a7c03e9..be90d3598bca 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c | |||
@@ -1143,12 +1143,12 @@ static int cnic_submit_bnx2_kwqes(struct cnic_dev *dev, struct kwqe *wqes[], | |||
1143 | 1143 | ||
1144 | spin_lock_bh(&cp->cnic_ulp_lock); | 1144 | spin_lock_bh(&cp->cnic_ulp_lock); |
1145 | if (num_wqes > cnic_kwq_avail(cp) && | 1145 | if (num_wqes > cnic_kwq_avail(cp) && |
1146 | !(cp->cnic_local_flags & CNIC_LCL_FL_KWQ_INIT)) { | 1146 | !test_bit(CNIC_LCL_FL_KWQ_INIT, &cp->cnic_local_flags)) { |
1147 | spin_unlock_bh(&cp->cnic_ulp_lock); | 1147 | spin_unlock_bh(&cp->cnic_ulp_lock); |
1148 | return -EAGAIN; | 1148 | return -EAGAIN; |
1149 | } | 1149 | } |
1150 | 1150 | ||
1151 | cp->cnic_local_flags &= ~CNIC_LCL_FL_KWQ_INIT; | 1151 | clear_bit(CNIC_LCL_FL_KWQ_INIT, &cp->cnic_local_flags); |
1152 | 1152 | ||
1153 | prod = cp->kwq_prod_idx; | 1153 | prod = cp->kwq_prod_idx; |
1154 | sw_prod = prod & MAX_KWQ_IDX; | 1154 | sw_prod = prod & MAX_KWQ_IDX; |
@@ -2092,7 +2092,6 @@ end: | |||
2092 | i += j; | 2092 | i += j; |
2093 | j = 1; | 2093 | j = 1; |
2094 | } | 2094 | } |
2095 | return; | ||
2096 | } | 2095 | } |
2097 | 2096 | ||
2098 | static u16 cnic_bnx2_next_idx(u16 idx) | 2097 | static u16 cnic_bnx2_next_idx(u16 idx) |
@@ -2146,17 +2145,56 @@ static int cnic_get_kcqes(struct cnic_dev *dev, u16 hw_prod, u16 *sw_prod) | |||
2146 | return last_cnt; | 2145 | return last_cnt; |
2147 | } | 2146 | } |
2148 | 2147 | ||
2148 | static int cnic_l2_completion(struct cnic_local *cp) | ||
2149 | { | ||
2150 | u16 hw_cons, sw_cons; | ||
2151 | union eth_rx_cqe *cqe, *cqe_ring = (union eth_rx_cqe *) | ||
2152 | (cp->l2_ring + (2 * BCM_PAGE_SIZE)); | ||
2153 | u32 cmd; | ||
2154 | int comp = 0; | ||
2155 | |||
2156 | if (!test_bit(CNIC_F_BNX2X_CLASS, &cp->dev->flags)) | ||
2157 | return 0; | ||
2158 | |||
2159 | hw_cons = *cp->rx_cons_ptr; | ||
2160 | if ((hw_cons & BNX2X_MAX_RCQ_DESC_CNT) == BNX2X_MAX_RCQ_DESC_CNT) | ||
2161 | hw_cons++; | ||
2162 | |||
2163 | sw_cons = cp->rx_cons; | ||
2164 | while (sw_cons != hw_cons) { | ||
2165 | u8 cqe_fp_flags; | ||
2166 | |||
2167 | cqe = &cqe_ring[sw_cons & BNX2X_MAX_RCQ_DESC_CNT]; | ||
2168 | cqe_fp_flags = cqe->fast_path_cqe.type_error_flags; | ||
2169 | if (cqe_fp_flags & ETH_FAST_PATH_RX_CQE_TYPE) { | ||
2170 | cmd = le32_to_cpu(cqe->ramrod_cqe.conn_and_cmd_data); | ||
2171 | cmd >>= COMMON_RAMROD_ETH_RX_CQE_CMD_ID_SHIFT; | ||
2172 | if (cmd == RAMROD_CMD_ID_ETH_CLIENT_SETUP || | ||
2173 | cmd == RAMROD_CMD_ID_ETH_HALT) | ||
2174 | comp++; | ||
2175 | } | ||
2176 | sw_cons = BNX2X_NEXT_RCQE(sw_cons); | ||
2177 | } | ||
2178 | return comp; | ||
2179 | } | ||
2180 | |||
2149 | static void cnic_chk_pkt_rings(struct cnic_local *cp) | 2181 | static void cnic_chk_pkt_rings(struct cnic_local *cp) |
2150 | { | 2182 | { |
2151 | u16 rx_cons = *cp->rx_cons_ptr; | 2183 | u16 rx_cons = *cp->rx_cons_ptr; |
2152 | u16 tx_cons = *cp->tx_cons_ptr; | 2184 | u16 tx_cons = *cp->tx_cons_ptr; |
2185 | int comp = 0; | ||
2153 | 2186 | ||
2154 | if (cp->tx_cons != tx_cons || cp->rx_cons != rx_cons) { | 2187 | if (cp->tx_cons != tx_cons || cp->rx_cons != rx_cons) { |
2188 | if (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags)) | ||
2189 | comp = cnic_l2_completion(cp); | ||
2190 | |||
2155 | cp->tx_cons = tx_cons; | 2191 | cp->tx_cons = tx_cons; |
2156 | cp->rx_cons = rx_cons; | 2192 | cp->rx_cons = rx_cons; |
2157 | 2193 | ||
2158 | uio_event_notify(cp->cnic_uinfo); | 2194 | uio_event_notify(cp->cnic_uinfo); |
2159 | } | 2195 | } |
2196 | if (comp) | ||
2197 | clear_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags); | ||
2160 | } | 2198 | } |
2161 | 2199 | ||
2162 | static int cnic_service_bnx2(void *data, void *status_blk) | 2200 | static int cnic_service_bnx2(void *data, void *status_blk) |
@@ -2325,7 +2363,6 @@ done: | |||
2325 | status_idx, IGU_INT_ENABLE, 1); | 2363 | status_idx, IGU_INT_ENABLE, 1); |
2326 | 2364 | ||
2327 | cp->kcq_prod_idx = sw_prod; | 2365 | cp->kcq_prod_idx = sw_prod; |
2328 | return; | ||
2329 | } | 2366 | } |
2330 | 2367 | ||
2331 | static int cnic_service_bnx2x(void *data, void *status_blk) | 2368 | static int cnic_service_bnx2x(void *data, void *status_blk) |
@@ -3692,7 +3729,7 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev) | |||
3692 | cp->max_kwq_idx = MAX_KWQ_IDX; | 3729 | cp->max_kwq_idx = MAX_KWQ_IDX; |
3693 | cp->kwq_prod_idx = 0; | 3730 | cp->kwq_prod_idx = 0; |
3694 | cp->kwq_con_idx = 0; | 3731 | cp->kwq_con_idx = 0; |
3695 | cp->cnic_local_flags |= CNIC_LCL_FL_KWQ_INIT; | 3732 | set_bit(CNIC_LCL_FL_KWQ_INIT, &cp->cnic_local_flags); |
3696 | 3733 | ||
3697 | if (CHIP_NUM(cp) == CHIP_NUM_5706 || CHIP_NUM(cp) == CHIP_NUM_5708) | 3734 | if (CHIP_NUM(cp) == CHIP_NUM_5706 || CHIP_NUM(cp) == CHIP_NUM_5708) |
3698 | cp->kwq_con_idx_ptr = &sblk->status_rx_quick_consumer_index15; | 3735 | cp->kwq_con_idx_ptr = &sblk->status_rx_quick_consumer_index15; |
@@ -4170,6 +4207,8 @@ static void cnic_init_rings(struct cnic_dev *dev) | |||
4170 | for (i = 0; i < sizeof(struct ustorm_eth_rx_producers) / 4; i++) | 4207 | for (i = 0; i < sizeof(struct ustorm_eth_rx_producers) / 4; i++) |
4171 | CNIC_WR(dev, off + i * 4, ((u32 *) &rx_prods)[i]); | 4208 | CNIC_WR(dev, off + i * 4, ((u32 *) &rx_prods)[i]); |
4172 | 4209 | ||
4210 | set_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags); | ||
4211 | |||
4173 | cnic_init_bnx2x_tx_ring(dev); | 4212 | cnic_init_bnx2x_tx_ring(dev); |
4174 | cnic_init_bnx2x_rx_ring(dev); | 4213 | cnic_init_bnx2x_rx_ring(dev); |
4175 | 4214 | ||
@@ -4177,6 +4216,15 @@ static void cnic_init_rings(struct cnic_dev *dev) | |||
4177 | l5_data.phy_address.hi = 0; | 4216 | l5_data.phy_address.hi = 0; |
4178 | cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_ETH_CLIENT_SETUP, | 4217 | cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_ETH_CLIENT_SETUP, |
4179 | BNX2X_ISCSI_L2_CID, ETH_CONNECTION_TYPE, &l5_data); | 4218 | BNX2X_ISCSI_L2_CID, ETH_CONNECTION_TYPE, &l5_data); |
4219 | i = 0; | ||
4220 | while (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags) && | ||
4221 | ++i < 10) | ||
4222 | msleep(1); | ||
4223 | |||
4224 | if (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags)) | ||
4225 | netdev_err(dev->netdev, | ||
4226 | "iSCSI CLIENT_SETUP did not complete\n"); | ||
4227 | cnic_kwq_completion(dev, 1); | ||
4180 | cnic_ring_ctl(dev, BNX2X_ISCSI_L2_CID, cli, 1); | 4228 | cnic_ring_ctl(dev, BNX2X_ISCSI_L2_CID, cli, 1); |
4181 | } | 4229 | } |
4182 | } | 4230 | } |
@@ -4189,14 +4237,25 @@ static void cnic_shutdown_rings(struct cnic_dev *dev) | |||
4189 | struct cnic_local *cp = dev->cnic_priv; | 4237 | struct cnic_local *cp = dev->cnic_priv; |
4190 | u32 cli = BNX2X_ISCSI_CL_ID(CNIC_E1HVN(cp)); | 4238 | u32 cli = BNX2X_ISCSI_CL_ID(CNIC_E1HVN(cp)); |
4191 | union l5cm_specific_data l5_data; | 4239 | union l5cm_specific_data l5_data; |
4240 | int i; | ||
4192 | 4241 | ||
4193 | cnic_ring_ctl(dev, BNX2X_ISCSI_L2_CID, cli, 0); | 4242 | cnic_ring_ctl(dev, BNX2X_ISCSI_L2_CID, cli, 0); |
4194 | 4243 | ||
4244 | set_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags); | ||
4245 | |||
4195 | l5_data.phy_address.lo = cli; | 4246 | l5_data.phy_address.lo = cli; |
4196 | l5_data.phy_address.hi = 0; | 4247 | l5_data.phy_address.hi = 0; |
4197 | cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_ETH_HALT, | 4248 | cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_ETH_HALT, |
4198 | BNX2X_ISCSI_L2_CID, ETH_CONNECTION_TYPE, &l5_data); | 4249 | BNX2X_ISCSI_L2_CID, ETH_CONNECTION_TYPE, &l5_data); |
4199 | msleep(10); | 4250 | i = 0; |
4251 | while (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags) && | ||
4252 | ++i < 10) | ||
4253 | msleep(1); | ||
4254 | |||
4255 | if (test_bit(CNIC_LCL_FL_L2_WAIT, &cp->cnic_local_flags)) | ||
4256 | netdev_err(dev->netdev, | ||
4257 | "iSCSI CLIENT_HALT did not complete\n"); | ||
4258 | cnic_kwq_completion(dev, 1); | ||
4200 | 4259 | ||
4201 | memset(&l5_data, 0, sizeof(l5_data)); | 4260 | memset(&l5_data, 0, sizeof(l5_data)); |
4202 | cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_ETH_CFC_DEL, | 4261 | cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_ETH_CFC_DEL, |
@@ -4317,7 +4376,15 @@ static void cnic_stop_hw(struct cnic_dev *dev) | |||
4317 | { | 4376 | { |
4318 | if (test_bit(CNIC_F_CNIC_UP, &dev->flags)) { | 4377 | if (test_bit(CNIC_F_CNIC_UP, &dev->flags)) { |
4319 | struct cnic_local *cp = dev->cnic_priv; | 4378 | struct cnic_local *cp = dev->cnic_priv; |
4379 | int i = 0; | ||
4320 | 4380 | ||
4381 | /* Need to wait for the ring shutdown event to complete | ||
4382 | * before clearing the CNIC_UP flag. | ||
4383 | */ | ||
4384 | while (cp->uio_dev != -1 && i < 15) { | ||
4385 | msleep(100); | ||
4386 | i++; | ||
4387 | } | ||
4321 | clear_bit(CNIC_F_CNIC_UP, &dev->flags); | 4388 | clear_bit(CNIC_F_CNIC_UP, &dev->flags); |
4322 | rcu_assign_pointer(cp->ulp_ops[CNIC_ULP_L4], NULL); | 4389 | rcu_assign_pointer(cp->ulp_ops[CNIC_ULP_L4], NULL); |
4323 | synchronize_rcu(); | 4390 | synchronize_rcu(); |
@@ -4628,7 +4695,6 @@ static void __exit cnic_exit(void) | |||
4628 | { | 4695 | { |
4629 | unregister_netdevice_notifier(&cnic_netdev_notifier); | 4696 | unregister_netdevice_notifier(&cnic_netdev_notifier); |
4630 | cnic_release(); | 4697 | cnic_release(); |
4631 | return; | ||
4632 | } | 4698 | } |
4633 | 4699 | ||
4634 | module_init(cnic_init); | 4700 | module_init(cnic_init); |