Pull InfiniBand/RDMA updates from Roland Dreier: - IPoIB fixes from Doug Ledford and Erez Shitrit - iSER updates from Sagi Grimberg - mlx4 GUID handling changes from Yishai Hadas - other misc fixes * tag 'rdma-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband: (51 commits) mlx5: wrong page mask if CONFIG_ARCH_DMA_ADDR_T_64BIT enabled for 32Bit architectures IB/iser: Rewrite bounce buffer code path IB/iser: Bump version to 1.6 IB/iser: Remove code duplication for a single DMA entry IB/iser: Pass struct iser_mem_reg to iser_fast_reg_mr and iser_reg_sig_mr IB/iser: Modify struct iser_mem_reg members IB/iser: Make fastreg pool cache friendly IB/iser: Move PI context alloc/free to routines IB/iser: Move fastreg descriptor pool get/put to helper functions IB/iser: Merge build page-vec into register page-vec IB/iser: Get rid of struct iser_rdma_regd IB/iser: Remove redundant assignments in iser_reg_page_vec IB/iser: Move memory reg/dereg routines to iser_memory.c IB/iser: Don't pass ib_device to fall_to_bounce_buff routine IB/iser: Remove a redundant struct iser_data_buf IB/iser: Remove redundant cmd_data_len calculation IB/iser: Fix wrong calculation of protection buffer length IB/iser: Handle fastreg/local_inv completion errors IB/iser: Fix unload during ep_poll wrong dereference ib_srpt: convert printk's to pr_* functions ...
Unified · Split
| @@ -187,8 +187,10 @@ Check RDMA and NFS Setup · 186 unmodified lines | ||
| 187 | 187 | To further test the InfiniBand software stack, use IPoIB (this |
| 188 | 188 | assumes you have two IB hosts named host1 and host2): |
| 189 | 189 | |
| 190 | − host1$ ifconfig ib0 a.b.c.x | |
| 191 | − host2$ ifconfig ib0 a.b.c.y | |
| 190 | + host1$ ip link set dev ib0 up | |
| 191 | + host1$ ip address add dev ib0 a.b.c.x | |
| 192 | + host2$ ip link set dev ib0 up | |
| 193 | + host2$ ip address add dev ib0 a.b.c.y | |
| 192 | 194 | host1$ ping a.b.c.y |
| 193 | 195 | host2$ ping a.b.c.x |
| 194 | 196 | |
| @@ -229,7 +231,8 @@ NFS/RDMA Setup · 34 unmodified lines | ||
| 229 | 231 | |
| 230 | 232 | $ modprobe ib_mthca |
| 231 | 233 | $ modprobe ib_ipoib |
| 232 | − $ ifconfig ib0 a.b.c.d | |
| 234 | + $ ip li set dev ib0 up | |
| 235 | + $ ip addr add dev ib0 a.b.c.d | |
| 233 | 236 | |
| 234 | 237 | NOTE: use unique addresses for the client and server |
| 235 | 238 | |
| @@ -8803,6 +8803,15 @@ W: http://www.emulex.com · 8802 unmodified lines | ||
| 8803 | 8803 | S: Supported |
| 8804 | 8804 | F: drivers/net/ethernet/emulex/benet/ |
| 8805 | 8805 | |
| 8806 | +EMULEX ONECONNECT ROCE DRIVER | |
| 8807 | +M: Selvin Xavier <selvin.xavier@emulex.com> | |
| 8808 | +M: Devesh Sharma <devesh.sharma@emulex.com> | |
| 8809 | +M: Mitesh Ahuja <mitesh.ahuja@emulex.com> | |
| 8810 | +L: linux-rdma@vger.kernel.org | |
| 8811 | +W: http://www.emulex.com | |
| 8812 | +S: Supported | |
| 8813 | +F: drivers/infiniband/hw/ocrdma/ | |
| 8814 | + | |
| 8806 | 8815 | SFC NETWORK DRIVER |
| 8807 | 8816 | M: Solarflare linux maintainers <linux-net-drivers@solarflare.com> |
| 8808 | 8817 | M: Shradha Shah <sshah@solarflare.com> |
| @@ -99,12 +99,15 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, · 98 unmodified lines | ||
| 99 | 99 | if (dmasync) |
| 100 | 100 | dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs); |
| 101 | 101 | |
| 102 | + if (!size) | |
| 103 | + return ERR_PTR(-EINVAL); | |
| 104 | + | |
| 102 | 105 | /* |
| 103 | 106 | * If the combination of the addr and size requested for this memory |
| 104 | 107 | * region causes an integer overflow, return error. |
| 105 | 108 | */ |
| 106 | − if ((PAGE_ALIGN(addr + size) <= size) || | |
| 107 | − (PAGE_ALIGN(addr + size) <= addr)) | |
| 109 | + if (((addr + size) < addr) || | |
| 110 | + PAGE_ALIGN(addr + size) < (addr + size)) | |
| 108 | 111 | return ERR_PTR(-EINVAL); |
| 109 | 112 | |
| 110 | 113 | if (!can_do_mlock()) |
| @@ -246,6 +246,17 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, · 245 unmodified lines | ||
| 246 | 246 | kfree(uqp); |
| 247 | 247 | } |
| 248 | 248 | |
| 249 | + list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) { | |
| 250 | + struct ib_srq *srq = uobj->object; | |
| 251 | + struct ib_uevent_object *uevent = | |
| 252 | + container_of(uobj, struct ib_uevent_object, uobject); | |
| 253 | + | |
| 254 | + idr_remove_uobj(&ib_uverbs_srq_idr, uobj); | |
| 255 | + ib_destroy_srq(srq); | |
| 256 | + ib_uverbs_release_uevent(file, uevent); | |
| 257 | + kfree(uevent); | |
| 258 | + } | |
| 259 | + | |
| 249 | 260 | list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) { |
| 250 | 261 | struct ib_cq *cq = uobj->object; |
| 251 | 262 | struct ib_uverbs_event_file *ev_file = cq->cq_context; |
| @@ -258,17 +269,6 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, · 6 unmodified lines | ||
| 258 | 269 | kfree(ucq); |
| 259 | 270 | } |
| 260 | 271 | |
| 261 | − list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) { | |
| 262 | − struct ib_srq *srq = uobj->object; | |
| 263 | − struct ib_uevent_object *uevent = | |
| 264 | − container_of(uobj, struct ib_uevent_object, uobject); | |
| 265 | − | |
| 266 | − idr_remove_uobj(&ib_uverbs_srq_idr, uobj); | |
| 267 | − ib_destroy_srq(srq); | |
| 268 | − ib_uverbs_release_uevent(file, uevent); | |
| 269 | − kfree(uevent); | |
| 270 | − } | |
| 271 | − | |
| 272 | 272 | list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) { |
| 273 | 273 | struct ib_mr *mr = uobj->object; |
| 274 | 274 | |
| @@ -58,14 +58,19 @@ struct mlx4_alias_guid_work_context { · 57 unmodified lines | ||
| 58 | 58 | int query_id; |
| 59 | 59 | struct list_head list; |
| 60 | 60 | int block_num; |
| 61 | + ib_sa_comp_mask guid_indexes; | |
| 62 | + u8 method; | |
| 61 | 63 | }; |
| 62 | 64 | |
| 63 | 65 | struct mlx4_next_alias_guid_work { |
| 64 | 66 | u8 port; |
| 65 | 67 | u8 block_num; |
| 68 | + u8 method; | |
| 66 | 69 | struct mlx4_sriov_alias_guid_info_rec_det rec_det; |
| 67 | 70 | }; |
| 68 | 71 | |
| 72 | +static int get_low_record_time_index(struct mlx4_ib_dev *dev, u8 port, | |
| 73 | + int *resched_delay_sec); | |
| 69 | 74 | |
| 70 | 75 | void mlx4_ib_update_cache_on_guid_change(struct mlx4_ib_dev *dev, int block_num, |
| 71 | 76 | u8 port_num, u8 *p_data) |
| @@ -118,6 +123,57 @@ ib_sa_comp_mask mlx4_ib_get_aguid_comp_mask_from_ix(int index) · 46 unmodified lines | ||
| 118 | 123 | return IB_SA_COMP_MASK(4 + index); |
| 119 | 124 | } |
| 120 | 125 | |
| 126 | +void mlx4_ib_slave_alias_guid_event(struct mlx4_ib_dev *dev, int slave, | |
| 127 | + int port, int slave_init) | |
| 128 | +{ | |
| 129 | + __be64 curr_guid, required_guid; | |
| 130 | + int record_num = slave / 8; | |
| 131 | + int index = slave % 8; | |
| 132 | + int port_index = port - 1; | |
| 133 | + unsigned long flags; | |
| 134 | + int do_work = 0; | |
| 135 | + | |
| 136 | + spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags); | |
| 137 | + if (dev->sriov.alias_guid.ports_guid[port_index].state_flags & | |
| 138 | + GUID_STATE_NEED_PORT_INIT) | |
| 139 | + goto unlock; | |
| 140 | + if (!slave_init) { | |
| 141 | + curr_guid = *(__be64 *)&dev->sriov. | |
| 142 | + alias_guid.ports_guid[port_index]. | |
| 143 | + all_rec_per_port[record_num]. | |
| 144 | + all_recs[GUID_REC_SIZE * index]; | |
| 145 | + if (curr_guid == cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL) || | |
| 146 | + !curr_guid) | |
| 147 | + goto unlock; | |
| 148 | + required_guid = cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL); | |
| 149 | + } else { | |
| 150 | + required_guid = mlx4_get_admin_guid(dev->dev, slave, port); | |
| 151 | + if (required_guid == cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL)) | |
| 152 | + goto unlock; | |
| 153 | + } | |
| 154 | + *(__be64 *)&dev->sriov.alias_guid.ports_guid[port_index]. | |
| 155 | + all_rec_per_port[record_num]. | |
| 156 | + all_recs[GUID_REC_SIZE * index] = required_guid; | |
| 157 | + dev->sriov.alias_guid.ports_guid[port_index]. | |
| 158 | + all_rec_per_port[record_num].guid_indexes | |
| 159 | + |= mlx4_ib_get_aguid_comp_mask_from_ix(index); | |
| 160 | + dev->sriov.alias_guid.ports_guid[port_index]. | |
| 161 | + all_rec_per_port[record_num].status | |
| 162 | + = MLX4_GUID_INFO_STATUS_IDLE; | |
| 163 | + /* set to run immediately */ | |
| 164 | + dev->sriov.alias_guid.ports_guid[port_index]. | |
| 165 | + all_rec_per_port[record_num].time_to_run = 0; | |
| 166 | + dev->sriov.alias_guid.ports_guid[port_index]. | |
| 167 | + all_rec_per_port[record_num]. | |
| 168 | + guids_retry_schedule[index] = 0; | |
| 169 | + do_work = 1; | |
| 170 | +unlock: | |
| 171 | + spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags); | |
| 172 | + | |
| 173 | + if (do_work) | |
| 174 | + mlx4_ib_init_alias_guid_work(dev, port_index); | |
| 175 | +} | |
| 176 | + | |
| 121 | 177 | /* |
| 122 | 178 | * Whenever new GUID is set/unset (guid table change) create event and |
| 123 | 179 | * notify the relevant slave (master also should be notified). |
| @@ -138,10 +194,15 @@ void mlx4_ib_notify_slaves_on_guid_change(struct mlx4_ib_dev *dev, · 14 unmodified lines | ||
| 138 | 194 | enum slave_port_state prev_state; |
| 139 | 195 | __be64 tmp_cur_ag, form_cache_ag; |
| 140 | 196 | enum slave_port_gen_event gen_event; |
| 197 | + struct mlx4_sriov_alias_guid_info_rec_det *rec; | |
| 198 | + unsigned long flags; | |
| 199 | + __be64 required_value; | |
| 141 | 200 | |
| 142 | 201 | if (!mlx4_is_master(dev->dev)) |
| 143 | 202 | return; |
| 144 | 203 | |
| 204 | + rec = &dev->sriov.alias_guid.ports_guid[port_num - 1]. | |
| 205 | + all_rec_per_port[block_num]; | |
| 145 | 206 | guid_indexes = be64_to_cpu((__force __be64) dev->sriov.alias_guid. |
| 146 | 207 | ports_guid[port_num - 1]. |
| 147 | 208 | all_rec_per_port[block_num].guid_indexes); |
| @@ -166,8 +227,27 @@ void mlx4_ib_notify_slaves_on_guid_change(struct mlx4_ib_dev *dev, · 18 unmodified lines | ||
| 166 | 227 | */ |
| 167 | 228 | if (tmp_cur_ag != form_cache_ag) |
| 168 | 229 | continue; |
| 169 | − mlx4_gen_guid_change_eqe(dev->dev, slave_id, port_num); | |
| 170 | 230 | |
| 231 | + spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags); | |
| 232 | + required_value = *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE]; | |
| 233 | + | |
| 234 | + if (required_value == cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL)) | |
| 235 | + required_value = 0; | |
| 236 | + | |
| 237 | + if (tmp_cur_ag == required_value) { | |
| 238 | + rec->guid_indexes = rec->guid_indexes & | |
| 239 | + ~mlx4_ib_get_aguid_comp_mask_from_ix(i); | |
| 240 | + } else { | |
| 241 | + /* may notify port down if value is 0 */ | |
| 242 | + if (tmp_cur_ag != MLX4_NOT_SET_GUID) { | |
| 243 | + spin_unlock_irqrestore(&dev->sriov. | |
| 244 | + alias_guid.ag_work_lock, flags); | |
| 245 | + continue; | |
| 246 | + } | |
| 247 | + } | |
| 248 | + spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, | |
| 249 | + flags); | |
| 250 | + mlx4_gen_guid_change_eqe(dev->dev, slave_id, port_num); | |
| 171 | 251 | /*2 cases: Valid GUID, and Invalid Guid*/ |
| 172 | 252 | |
| 173 | 253 | if (tmp_cur_ag != MLX4_NOT_SET_GUID) { /*valid GUID*/ |
| @@ -188,10 +268,14 @@ void mlx4_ib_notify_slaves_on_guid_change(struct mlx4_ib_dev *dev, · 14 unmodified lines | ||
| 188 | 268 | set_and_calc_slave_port_state(dev->dev, slave_id, port_num, |
| 189 | 269 | MLX4_PORT_STATE_IB_EVENT_GID_INVALID, |
| 190 | 270 | &gen_event); |
| 191 | − pr_debug("sending PORT DOWN event to slave: %d, port: %d\n", | |
| 192 | − slave_id, port_num); | |
| 193 | − mlx4_gen_port_state_change_eqe(dev->dev, slave_id, port_num, | |
| 194 | − MLX4_PORT_CHANGE_SUBTYPE_DOWN); | |
| 271 | + if (gen_event == SLAVE_PORT_GEN_EVENT_DOWN) { | |
| 272 | + pr_debug("sending PORT DOWN event to slave: %d, port: %d\n", | |
| 273 | + slave_id, port_num); | |
| 274 | + mlx4_gen_port_state_change_eqe(dev->dev, | |
| 275 | + slave_id, | |
| 276 | + port_num, | |
| 277 | + MLX4_PORT_CHANGE_SUBTYPE_DOWN); | |
| 278 | + } | |
| 195 | 279 | } |
| 196 | 280 | } |
| 197 | 281 | } |
| @@ -206,6 +290,9 @@ static void aliasguid_query_handler(int status, · 8 unmodified lines | ||
| 206 | 290 | int i; |
| 207 | 291 | struct mlx4_sriov_alias_guid_info_rec_det *rec; |
| 208 | 292 | unsigned long flags, flags1; |
| 293 | + ib_sa_comp_mask declined_guid_indexes = 0; | |
| 294 | + ib_sa_comp_mask applied_guid_indexes = 0; | |
| 295 | + unsigned int resched_delay_sec = 0; | |
| 209 | 296 | |
| 210 | 297 | if (!context) |
| 211 | 298 | return; |
| @@ -216,9 +303,9 @@ static void aliasguid_query_handler(int status, · 4 unmodified lines | ||
| 216 | 303 | all_rec_per_port[cb_ctx->block_num]; |
| 217 | 304 | |
| 218 | 305 | if (status) { |
| 219 | − rec->status = MLX4_GUID_INFO_STATUS_IDLE; | |
| 220 | 306 | pr_debug("(port: %d) failed: status = %d\n", |
| 221 | 307 | cb_ctx->port, status); |
| 308 | + rec->time_to_run = ktime_get_real_ns() + 1 * NSEC_PER_SEC; | |
| 222 | 309 | goto out; |
| 223 | 310 | } |
| 224 | 311 | |
| @@ -235,57 +322,101 @@ static void aliasguid_query_handler(int status, · 10 unmodified lines | ||
| 235 | 322 | rec = &dev->sriov.alias_guid.ports_guid[port_index]. |
| 236 | 323 | all_rec_per_port[guid_rec->block_num]; |
| 237 | 324 | |
| 238 | − rec->status = MLX4_GUID_INFO_STATUS_SET; | |
| 239 | − rec->method = MLX4_GUID_INFO_RECORD_SET; | |
| 240 | − | |
| 325 | + spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags); | |
| 241 | 326 | for (i = 0 ; i < NUM_ALIAS_GUID_IN_REC; i++) { |
| 242 | − __be64 tmp_cur_ag; | |
| 243 | − tmp_cur_ag = *(__be64 *)&guid_rec->guid_info_list[i * GUID_REC_SIZE]; | |
| 327 | + __be64 sm_response, required_val; | |
| 328 | + | |
| 329 | + if (!(cb_ctx->guid_indexes & | |
| 330 | + mlx4_ib_get_aguid_comp_mask_from_ix(i))) | |
| 331 | + continue; | |
| 332 | + sm_response = *(__be64 *)&guid_rec->guid_info_list | |
| 333 | + [i * GUID_REC_SIZE]; | |
| 334 | + required_val = *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE]; | |
| 335 | + if (cb_ctx->method == MLX4_GUID_INFO_RECORD_DELETE) { | |
| 336 | + if (required_val == | |
| 337 | + cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL)) | |
| 338 | + goto next_entry; | |
| 339 | + | |
| 340 | + /* A new value was set till we got the response */ | |
| 341 | + pr_debug("need to set new value %llx, record num %d, block_num:%d\n", | |
| 342 | + be64_to_cpu(required_val), | |
| 343 | + i, guid_rec->block_num); | |
| 344 | + goto entry_declined; | |
| 345 | + } | |
| 346 | + | |
| 244 | 347 | /* check if the SM didn't assign one of the records. |
| 245 | − * if it didn't, if it was not sysadmin request: | |
| 246 | − * ask the SM to give a new GUID, (instead of the driver request). | |
| 348 | + * if it didn't, re-ask for. | |
| 247 | 349 | */ |
| 248 | − if (tmp_cur_ag == MLX4_NOT_SET_GUID) { | |
| 249 | − mlx4_ib_warn(&dev->ib_dev, "%s:Record num %d in " | |
| 250 | − "block_num: %d was declined by SM, " | |
| 251 | − "ownership by %d (0 = driver, 1=sysAdmin," | |
| 252 | − " 2=None)\n", __func__, i, | |
| 253 | − guid_rec->block_num, rec->ownership); | |
| 254 | − if (rec->ownership == MLX4_GUID_DRIVER_ASSIGN) { | |
| 255 | − /* if it is driver assign, asks for new GUID from SM*/ | |
| 256 | − *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE] = | |
| 257 | − MLX4_NOT_SET_GUID; | |
| 258 | − | |
| 259 | − /* Mark the record as not assigned, and let it | |
| 260 | − * be sent again in the next work sched.*/ | |
| 261 | − rec->status = MLX4_GUID_INFO_STATUS_IDLE; | |
| 262 | − rec->guid_indexes |= mlx4_ib_get_aguid_comp_mask_from_ix(i); | |
| 263 | − } | |
| 350 | + if (sm_response == MLX4_NOT_SET_GUID) { | |
| 351 | + if (rec->guids_retry_schedule[i] == 0) | |
| 352 | + mlx4_ib_warn(&dev->ib_dev, | |
| 353 | + "%s:Record num %d in block_num: %d was declined by SM\n", | |
| 354 | + __func__, i, | |
| 355 | + guid_rec->block_num); | |
| 356 | + goto entry_declined; | |
| 264 | 357 | } else { |
| 265 | 358 | /* properly assigned record. */ |
| 266 | 359 | /* We save the GUID we just got from the SM in the |
| 267 | 360 | * admin_guid in order to be persistent, and in the |
| 268 | 361 | * request from the sm the process will ask for the same GUID */ |
| 269 | − if (rec->ownership == MLX4_GUID_SYSADMIN_ASSIGN && | |
| 270 | − tmp_cur_ag != *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE]) { | |
| 271 | − /* the sysadmin assignment failed.*/ | |
| 272 | − mlx4_ib_warn(&dev->ib_dev, "%s: Failed to set" | |
| 273 | − " admin guid after SysAdmin " | |
| 274 | − "configuration. " | |
| 275 | − "Record num %d in block_num:%d " | |
| 276 | − "was declined by SM, " | |
| 277 | − "new val(0x%llx) was kept\n", | |
| 278 | − __func__, i, | |
| 279 | − guid_rec->block_num, | |
| 280 | − be64_to_cpu(*(__be64 *) & | |
| 281 | − rec->all_recs[i * GUID_REC_SIZE])); | |
| 362 | + if (required_val && | |
| 363 | + sm_response != required_val) { | |
| 364 | + /* Warn only on first retry */ | |
| 365 | + if (rec->guids_retry_schedule[i] == 0) | |
| 366 | + mlx4_ib_warn(&dev->ib_dev, "%s: Failed to set" | |
| 367 | + " admin guid after SysAdmin " | |
| 368 | + "configuration. " | |
| 369 | + "Record num %d in block_num:%d " | |
| 370 | + "was declined by SM, " | |
| 371 | + "new val(0x%llx) was kept, SM returned (0x%llx)\n", | |
| 372 | + __func__, i, | |
| 373 | + guid_rec->block_num, | |
| 374 | + be64_to_cpu(required_val), | |
| 375 | + be64_to_cpu(sm_response)); | |
| 376 | + goto entry_declined; | |
| 282 | 377 | } else { |
| 283 | − memcpy(&rec->all_recs[i * GUID_REC_SIZE], | |
| 284 | − &guid_rec->guid_info_list[i * GUID_REC_SIZE], | |
| 285 | − GUID_REC_SIZE); | |
| 378 | + *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE] = | |
| 379 | + sm_response; | |
| 380 | + if (required_val == 0) | |
| 381 | + mlx4_set_admin_guid(dev->dev, | |
| 382 | + sm_response, | |
| 383 | + (guid_rec->block_num | |
| 384 | + * NUM_ALIAS_GUID_IN_REC) + i, | |
| 385 | + cb_ctx->port); | |
| 386 | + goto next_entry; | |
| 286 | 387 | } |
| 287 | 388 | } |
| 389 | +entry_declined: | |
| 390 | + declined_guid_indexes |= mlx4_ib_get_aguid_comp_mask_from_ix(i); | |
| 391 | + rec->guids_retry_schedule[i] = | |
| 392 | + (rec->guids_retry_schedule[i] == 0) ? 1 : | |
| 393 | + min((unsigned int)60, | |
| 394 | + rec->guids_retry_schedule[i] * 2); | |
| 395 | + /* using the minimum value among all entries in that record */ | |
| 396 | + resched_delay_sec = (resched_delay_sec == 0) ? | |
| 397 | + rec->guids_retry_schedule[i] : | |
| 398 | + min(resched_delay_sec, | |
| 399 | + rec->guids_retry_schedule[i]); | |
| 400 | + continue; | |
| 401 | + | |
| 402 | +next_entry: | |
| 403 | + rec->guids_retry_schedule[i] = 0; | |
| 288 | 404 | } |
| 405 | + | |
| 406 | + applied_guid_indexes = cb_ctx->guid_indexes & ~declined_guid_indexes; | |
| 407 | + if (declined_guid_indexes || | |
| 408 | + rec->guid_indexes & ~(applied_guid_indexes)) { | |
| 409 | + pr_debug("record=%d wasn't fully set, guid_indexes=0x%llx applied_indexes=0x%llx, declined_indexes=0x%llx\n", | |
| 410 | + guid_rec->block_num, | |
| 411 | + be64_to_cpu((__force __be64)rec->guid_indexes), | |
| 412 | + be64_to_cpu((__force __be64)applied_guid_indexes), | |
| 413 | + be64_to_cpu((__force __be64)declined_guid_indexes)); | |
| 414 | + rec->time_to_run = ktime_get_real_ns() + | |
| 415 | + resched_delay_sec * NSEC_PER_SEC; | |
| 416 | + } else { | |
| 417 | + rec->status = MLX4_GUID_INFO_STATUS_SET; | |
| 418 | + } | |
| 419 | + spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags); | |
| 289 | 420 | /* |
| 290 | 421 | The func is call here to close the cases when the |
| 291 | 422 | sm doesn't send smp, so in the sa response the driver |
| @@ -297,10 +428,13 @@ static void aliasguid_query_handler(int status, · 5 unmodified lines | ||
| 297 | 428 | out: |
| 298 | 429 | spin_lock_irqsave(&dev->sriov.going_down_lock, flags); |
| 299 | 430 | spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1); |
| 300 | − if (!dev->sriov.is_going_down) | |
| 431 | + if (!dev->sriov.is_going_down) { | |
| 432 | + get_low_record_time_index(dev, port_index, &resched_delay_sec); | |
| 301 | 433 | queue_delayed_work(dev->sriov.alias_guid.ports_guid[port_index].wq, |
| 302 | 434 | &dev->sriov.alias_guid.ports_guid[port_index]. |
| 303 | − alias_guid_work, 0); | |
| 435 | + alias_guid_work, | |
| 436 | + msecs_to_jiffies(resched_delay_sec * 1000)); | |
| 437 | + } | |
| 304 | 438 | if (cb_ctx->sa_query) { |
| 305 | 439 | list_del(&cb_ctx->list); |
| 306 | 440 | kfree(cb_ctx); |
| @@ -317,9 +451,7 @@ static void invalidate_guid_record(struct mlx4_ib_dev *dev, u8 port, int index) · 10 unmodified lines | ||
| 317 | 451 | ib_sa_comp_mask comp_mask = 0; |
| 318 | 452 | |
| 319 | 453 | dev->sriov.alias_guid.ports_guid[port - 1].all_rec_per_port[index].status |
| 320 | − = MLX4_GUID_INFO_STATUS_IDLE; | |
| 321 | − dev->sriov.alias_guid.ports_guid[port - 1].all_rec_per_port[index].method | |
| 322 | − = MLX4_GUID_INFO_RECORD_SET; | |
| 454 | + = MLX4_GUID_INFO_STATUS_SET; | |
| 323 | 455 | |
| 324 | 456 | /* calculate the comp_mask for that record.*/ |
| 325 | 457 | for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) { |
| @@ -333,19 +465,21 @@ static void invalidate_guid_record(struct mlx4_ib_dev *dev, u8 port, int index) · 7 unmodified lines | ||
| 333 | 465 | need to assign GUIDs, then don't put it up for assignment. |
| 334 | 466 | */ |
| 335 | 467 | if (MLX4_GUID_FOR_DELETE_VAL == cur_admin_val || |
| 336 | − (!index && !i) || | |
| 337 | − MLX4_GUID_NONE_ASSIGN == dev->sriov.alias_guid. | |
| 338 | − ports_guid[port - 1].all_rec_per_port[index].ownership) | |
| 468 | + (!index && !i)) | |
| 339 | 469 | continue; |
| 340 | 470 | comp_mask |= mlx4_ib_get_aguid_comp_mask_from_ix(i); |
| 341 | 471 | } |
| 342 | 472 | dev->sriov.alias_guid.ports_guid[port - 1]. |
| 343 | − all_rec_per_port[index].guid_indexes = comp_mask; | |
| 473 | + all_rec_per_port[index].guid_indexes |= comp_mask; | |
| 474 | + if (dev->sriov.alias_guid.ports_guid[port - 1]. | |
| 475 | + all_rec_per_port[index].guid_indexes) | |
| 476 | + dev->sriov.alias_guid.ports_guid[port - 1]. | |
| 477 | + all_rec_per_port[index].status = MLX4_GUID_INFO_STATUS_IDLE; | |
| 478 | + | |
| 344 | 479 | } |
| 345 | 480 | |
| 346 | 481 | static int set_guid_rec(struct ib_device *ibdev, |
| 347 | − u8 port, int index, | |
| 348 | − struct mlx4_sriov_alias_guid_info_rec_det *rec_det) | |
| 482 | + struct mlx4_next_alias_guid_work *rec) | |
| 349 | 483 | { |
| 350 | 484 | int err; |
| 351 | 485 | struct mlx4_ib_dev *dev = to_mdev(ibdev); |
| @@ -354,6 +488,9 @@ static int set_guid_rec(struct ib_device *ibdev, · 2 unmodified lines | ||
| 354 | 488 | struct ib_port_attr attr; |
| 355 | 489 | struct mlx4_alias_guid_work_context *callback_context; |
| 356 | 490 | unsigned long resched_delay, flags, flags1; |
| 491 | + u8 port = rec->port + 1; | |
| 492 | + int index = rec->block_num; | |
| 493 | + struct mlx4_sriov_alias_guid_info_rec_det *rec_det = &rec->rec_det; | |
| 357 | 494 | struct list_head *head = |
| 358 | 495 | &dev->sriov.alias_guid.ports_guid[port - 1].cb_list; |
| 359 | 496 | |
| @@ -380,6 +517,8 @@ static int set_guid_rec(struct ib_device *ibdev, · 20 unmodified lines | ||
| 380 | 517 | callback_context->port = port; |
| 381 | 518 | callback_context->dev = dev; |
| 382 | 519 | callback_context->block_num = index; |
| 520 | + callback_context->guid_indexes = rec_det->guid_indexes; | |
| 521 | + callback_context->method = rec->method; | |
| 383 | 522 | |
| 384 | 523 | memset(&guid_info_rec, 0, sizeof (struct ib_sa_guidinfo_rec)); |
| 385 | 524 | |
| @@ -399,7 +538,7 @@ static int set_guid_rec(struct ib_device *ibdev, · 13 unmodified lines | ||
| 399 | 538 | callback_context->query_id = |
| 400 | 539 | ib_sa_guid_info_rec_query(dev->sriov.alias_guid.sa_client, |
| 401 | 540 | ibdev, port, &guid_info_rec, |
| 402 | − comp_mask, rec_det->method, 1000, | |
| 541 | + comp_mask, rec->method, 1000, | |
| 403 | 542 | GFP_KERNEL, aliasguid_query_handler, |
| 404 | 543 | callback_context, |
| 405 | 544 | &callback_context->sa_query); |
| @@ -434,6 +573,30 @@ out: · 28 unmodified lines | ||
| 434 | 573 | return err; |
| 435 | 574 | } |
| 436 | 575 | |
| 576 | +static void mlx4_ib_guid_port_init(struct mlx4_ib_dev *dev, int port) | |
| 577 | +{ | |
| 578 | + int j, k, entry; | |
| 579 | + __be64 guid; | |
| 580 | + | |
| 581 | + /*Check if the SM doesn't need to assign the GUIDs*/ | |
| 582 | + for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) { | |
| 583 | + for (k = 0; k < NUM_ALIAS_GUID_IN_REC; k++) { | |
| 584 | + entry = j * NUM_ALIAS_GUID_IN_REC + k; | |
| 585 | + /* no request for the 0 entry (hw guid) */ | |
| 586 | + if (!entry || entry > dev->dev->persist->num_vfs || | |
| 587 | + !mlx4_is_slave_active(dev->dev, entry)) | |
| 588 | + continue; | |
| 589 | + guid = mlx4_get_admin_guid(dev->dev, entry, port); | |
| 590 | + *(__be64 *)&dev->sriov.alias_guid.ports_guid[port - 1]. | |
| 591 | + all_rec_per_port[j].all_recs | |
| 592 | + [GUID_REC_SIZE * k] = guid; | |
| 593 | + pr_debug("guid was set, entry=%d, val=0x%llx, port=%d\n", | |
| 594 | + entry, | |
| 595 | + be64_to_cpu(guid), | |
| 596 | + port); | |
| 597 | + } | |
| 598 | + } | |
| 599 | +} | |
| 437 | 600 | void mlx4_ib_invalidate_all_guid_record(struct mlx4_ib_dev *dev, int port) |
| 438 | 601 | { |
| 439 | 602 | int i; |
| @@ -443,6 +606,13 @@ void mlx4_ib_invalidate_all_guid_record(struct mlx4_ib_dev *dev, int port) · 3 unmodified lines | ||
| 443 | 606 | |
| 444 | 607 | spin_lock_irqsave(&dev->sriov.going_down_lock, flags); |
| 445 | 608 | spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1); |
| 609 | + | |
| 610 | + if (dev->sriov.alias_guid.ports_guid[port - 1].state_flags & | |
| 611 | + GUID_STATE_NEED_PORT_INIT) { | |
| 612 | + mlx4_ib_guid_port_init(dev, port); | |
| 613 | + dev->sriov.alias_guid.ports_guid[port - 1].state_flags &= | |
| 614 | + (~GUID_STATE_NEED_PORT_INIT); | |
| 615 | + } | |
| 446 | 616 | for (i = 0; i < NUM_ALIAS_GUID_REC_IN_PORT; i++) |
| 447 | 617 | invalidate_guid_record(dev, port, i); |
| 448 | 618 | |
| @@ -462,60 +632,107 @@ void mlx4_ib_invalidate_all_guid_record(struct mlx4_ib_dev *dev, int port) · 13 unmodified lines | ||
| 462 | 632 | spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags); |
| 463 | 633 | } |
| 464 | 634 | |
| 465 | −/* The function returns the next record that was | |
| 466 | − * not configured (or failed to be configured) */ | |
| 467 | −static int get_next_record_to_update(struct mlx4_ib_dev *dev, u8 port, | |
| 468 | − struct mlx4_next_alias_guid_work *rec) | |
| 635 | +static void set_required_record(struct mlx4_ib_dev *dev, u8 port, | |
| 636 | + struct mlx4_next_alias_guid_work *next_rec, | |
| 637 | + int record_index) | |
| 469 | 638 | { |
| 470 | − int j; | |
| 471 | − unsigned long flags; | |
| 639 | + int i; | |
| 640 | + int lowset_time_entry = -1; | |
| 641 | + int lowest_time = 0; | |
| 642 | + ib_sa_comp_mask delete_guid_indexes = 0; | |
| 643 | + ib_sa_comp_mask set_guid_indexes = 0; | |
| 644 | + struct mlx4_sriov_alias_guid_info_rec_det *rec = | |
| 645 | + &dev->sriov.alias_guid.ports_guid[port]. | |
| 646 | + all_rec_per_port[record_index]; | |
| 472 | 647 | |
| 473 | − for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) { | |
| 474 | − spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags); | |
| 475 | − if (dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[j].status == | |
| 476 | − MLX4_GUID_INFO_STATUS_IDLE) { | |
| 477 | − memcpy(&rec->rec_det, | |
| 478 | − &dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[j], | |
| 479 | − sizeof (struct mlx4_sriov_alias_guid_info_rec_det)); | |
| 480 | − rec->port = port; | |
| 481 | − rec->block_num = j; | |
| 482 | − dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[j].status = | |
| 483 | − MLX4_GUID_INFO_STATUS_PENDING; | |
| 484 | − spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags); | |
| 485 | − return 0; | |
| 648 | + for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) { | |
| 649 | + if (!(rec->guid_indexes & | |
| 650 | + mlx4_ib_get_aguid_comp_mask_from_ix(i))) | |
| 651 | + continue; | |
| 652 | + | |
| 653 | + if (*(__be64 *)&rec->all_recs[i * GUID_REC_SIZE] == | |
| 654 | + cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL)) | |
| 655 | + delete_guid_indexes |= | |
| 656 | + mlx4_ib_get_aguid_comp_mask_from_ix(i); | |
| 657 | + else | |
| 658 | + set_guid_indexes |= | |
| 659 | + mlx4_ib_get_aguid_comp_mask_from_ix(i); | |
| 660 | + | |
| 661 | + if (lowset_time_entry == -1 || rec->guids_retry_schedule[i] <= | |
| 662 | + lowest_time) { | |
| 663 | + lowset_time_entry = i; | |
| 664 | + lowest_time = rec->guids_retry_schedule[i]; | |
| 486 | 665 | } |
| 487 | − spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags); | |
| 488 | 666 | } |
| 489 | − return -ENOENT; | |
| 667 | + | |
| 668 | + memcpy(&next_rec->rec_det, rec, sizeof(*rec)); | |
| 669 | + next_rec->port = port; | |
| 670 | + next_rec->block_num = record_index; | |
| 671 | + | |
| 672 | + if (*(__be64 *)&rec->all_recs[lowset_time_entry * GUID_REC_SIZE] == | |
| 673 | + cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL)) { | |
| 674 | + next_rec->rec_det.guid_indexes = delete_guid_indexes; | |
| 675 | + next_rec->method = MLX4_GUID_INFO_RECORD_DELETE; | |
| 676 | + } else { | |
| 677 | + next_rec->rec_det.guid_indexes = set_guid_indexes; | |
| 678 | + next_rec->method = MLX4_GUID_INFO_RECORD_SET; | |
| 679 | + } | |
| 490 | 680 | } |
| 491 | 681 | |
| 492 | −static void set_administratively_guid_record(struct mlx4_ib_dev *dev, int port, | |
| 493 | − int rec_index, | |
| 494 | − struct mlx4_sriov_alias_guid_info_rec_det *rec_det) | |
| 682 | +/* return index of record that should be updated based on lowest | |
| 683 | + * rescheduled time | |
| 684 | + */ | |
| 685 | +static int get_low_record_time_index(struct mlx4_ib_dev *dev, u8 port, | |
| 686 | + int *resched_delay_sec) | |
| 495 | 687 | { |
| 496 | − dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[rec_index].guid_indexes = | |
| 497 | − rec_det->guid_indexes; | |
| 498 | − memcpy(dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[rec_index].all_recs, | |
| 499 | − rec_det->all_recs, NUM_ALIAS_GUID_IN_REC * GUID_REC_SIZE); | |
| 500 | − dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[rec_index].status = | |
| 501 | − rec_det->status; | |
| 688 | + int record_index = -1; | |
| 689 | + u64 low_record_time = 0; | |
| 690 | + struct mlx4_sriov_alias_guid_info_rec_det rec; | |
| 691 | + int j; | |
| 692 | + | |
| 693 | + for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) { | |
| 694 | + rec = dev->sriov.alias_guid.ports_guid[port]. | |
| 695 | + all_rec_per_port[j]; | |
| 696 | + if (rec.status == MLX4_GUID_INFO_STATUS_IDLE && | |
| 697 | + rec.guid_indexes) { | |
| 698 | + if (record_index == -1 || | |
| 699 | + rec.time_to_run < low_record_time) { | |
| 700 | + record_index = j; | |
| 701 | + low_record_time = rec.time_to_run; | |
| 702 | + } | |
| 703 | + } | |
| 704 | + } | |
| 705 | + if (resched_delay_sec) { | |
| 706 | + u64 curr_time = ktime_get_real_ns(); | |
| 707 | + | |
| 708 | + *resched_delay_sec = (low_record_time < curr_time) ? 0 : | |
| 709 | + div_u64((low_record_time - curr_time), NSEC_PER_SEC); | |
| 710 | + } | |
| 711 | + | |
| 712 | + return record_index; | |
| 502 | 713 | } |
| 503 | 714 | |
| 504 | −static void set_all_slaves_guids(struct mlx4_ib_dev *dev, int port) | |
| 715 | +/* The function returns the next record that was | |
| 716 | + * not configured (or failed to be configured) */ | |
| 717 | +static int get_next_record_to_update(struct mlx4_ib_dev *dev, u8 port, | |
| 718 | + struct mlx4_next_alias_guid_work *rec) | |
| 505 | 719 | { |
| 506 | − int j; | |
| 507 | − struct mlx4_sriov_alias_guid_info_rec_det rec_det ; | |
| 508 | − | |
| 509 | − for (j = 0 ; j < NUM_ALIAS_GUID_REC_IN_PORT ; j++) { | |
| 510 | − memset(rec_det.all_recs, 0, NUM_ALIAS_GUID_IN_REC * GUID_REC_SIZE); | |
| 511 | − rec_det.guid_indexes = (!j ? 0 : IB_SA_GUIDINFO_REC_GID0) | | |
| 512 | − IB_SA_GUIDINFO_REC_GID1 | IB_SA_GUIDINFO_REC_GID2 | | |
| 513 | − IB_SA_GUIDINFO_REC_GID3 | IB_SA_GUIDINFO_REC_GID4 | | |
| 514 | − IB_SA_GUIDINFO_REC_GID5 | IB_SA_GUIDINFO_REC_GID6 | | |
| 515 | − IB_SA_GUIDINFO_REC_GID7; | |
| 516 | − rec_det.status = MLX4_GUID_INFO_STATUS_IDLE; | |
| 517 | − set_administratively_guid_record(dev, port, j, &rec_det); | |
| 720 | + unsigned long flags; | |
| 721 | + int record_index; | |
| 722 | + int ret = 0; | |
| 723 | + | |
| 724 | + spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags); | |
| 725 | + record_index = get_low_record_time_index(dev, port, NULL); | |
| 726 | + | |
| 727 | + if (record_index < 0) { | |
| 728 | + ret = -ENOENT; | |
| 729 | + goto out; | |
| 518 | 730 | } |
| 731 | + | |
| 732 | + set_required_record(dev, port, rec, record_index); | |
| 733 | +out: | |
| 734 | + spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags); | |
| 735 | + return ret; | |
| 519 | 736 | } |
| 520 | 737 | |
| 521 | 738 | static void alias_guid_work(struct work_struct *work) |
| @@ -545,9 +762,7 @@ static void alias_guid_work(struct work_struct *work) · 23 unmodified lines | ||
| 545 | 762 | goto out; |
| 546 | 763 | } |
| 547 | 764 | |
| 548 | − set_guid_rec(&dev->ib_dev, rec->port + 1, rec->block_num, | |
| 549 | − &rec->rec_det); | |
| 550 | − | |
| 765 | + set_guid_rec(&dev->ib_dev, rec); | |
| 551 | 766 | out: |
| 552 | 767 | kfree(rec); |
| 553 | 768 | } |
| @@ -562,6 +777,12 @@ void mlx4_ib_init_alias_guid_work(struct mlx4_ib_dev *dev, int port) · 8 unmodified lines | ||
| 562 | 777 | spin_lock_irqsave(&dev->sriov.going_down_lock, flags); |
| 563 | 778 | spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1); |
| 564 | 779 | if (!dev->sriov.is_going_down) { |
| 780 | + /* If there is pending one should cancell then run, otherwise | |
| 781 | + * won't run till previous one is ended as same work | |
| 782 | + * struct is used. | |
| 783 | + */ | |
| 784 | + cancel_delayed_work(&dev->sriov.alias_guid.ports_guid[port]. | |
| 785 | + alias_guid_work); | |
| 565 | 786 | queue_delayed_work(dev->sriov.alias_guid.ports_guid[port].wq, |
| 566 | 787 | &dev->sriov.alias_guid.ports_guid[port].alias_guid_work, 0); |
| 567 | 788 | } |
| @@ -609,7 +830,7 @@ int mlx4_ib_init_alias_guid_service(struct mlx4_ib_dev *dev) · 41 unmodified lines | ||
| 609 | 830 | { |
| 610 | 831 | char alias_wq_name[15]; |
| 611 | 832 | int ret = 0; |
| 612 | − int i, j, k; | |
| 833 | + int i, j; | |
| 613 | 834 | union ib_gid gid; |
| 614 | 835 | |
| 615 | 836 | if (!mlx4_is_master(dev->dev)) |
| @@ -633,33 +854,25 @@ int mlx4_ib_init_alias_guid_service(struct mlx4_ib_dev *dev) · 17 unmodified lines | ||
| 633 | 854 | for (i = 0 ; i < dev->num_ports; i++) { |
| 634 | 855 | memset(&dev->sriov.alias_guid.ports_guid[i], 0, |
| 635 | 856 | sizeof (struct mlx4_sriov_alias_guid_port_rec_det)); |
| 636 | − /*Check if the SM doesn't need to assign the GUIDs*/ | |
| 857 | + dev->sriov.alias_guid.ports_guid[i].state_flags |= | |
| 858 | + GUID_STATE_NEED_PORT_INIT; | |
| 637 | 859 | for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) { |
| 638 | − if (mlx4_ib_sm_guid_assign) { | |
| 639 | − dev->sriov.alias_guid.ports_guid[i]. | |
| 640 | − all_rec_per_port[j]. | |
| 641 | − ownership = MLX4_GUID_DRIVER_ASSIGN; | |
| 642 | − continue; | |
| 643 | − } | |
| 644 | − dev->sriov.alias_guid.ports_guid[i].all_rec_per_port[j]. | |
| 645 | − ownership = MLX4_GUID_NONE_ASSIGN; | |
| 646 | − /*mark each val as it was deleted, | |
| 647 | − till the sysAdmin will give it valid val*/ | |
| 648 | − for (k = 0; k < NUM_ALIAS_GUID_IN_REC; k++) { | |
| 649 | − *(__be64 *)&dev->sriov.alias_guid.ports_guid[i]. | |
| 650 | − all_rec_per_port[j].all_recs[GUID_REC_SIZE * k] = | |
| 651 | − cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL); | |
| 652 | − } | |
| 860 | + /* mark each val as it was deleted */ | |
| 861 | + memset(dev->sriov.alias_guid.ports_guid[i]. | |
| 862 | + all_rec_per_port[j].all_recs, 0xFF, | |
| 863 | + sizeof(dev->sriov.alias_guid.ports_guid[i]. | |
| 864 | + all_rec_per_port[j].all_recs)); | |
| 653 | 865 | } |
| 654 | 866 | INIT_LIST_HEAD(&dev->sriov.alias_guid.ports_guid[i].cb_list); |
| 655 | 867 | /*prepare the records, set them to be allocated by sm*/ |
| 868 | + if (mlx4_ib_sm_guid_assign) | |
| 869 | + for (j = 1; j < NUM_ALIAS_GUID_PER_PORT; j++) | |
| 870 | + mlx4_set_admin_guid(dev->dev, 0, j, i + 1); | |
| 656 | 871 | for (j = 0 ; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) |
| 657 | 872 | invalidate_guid_record(dev, i + 1, j); |
| 658 | 873 | |
| 659 | 874 | dev->sriov.alias_guid.ports_guid[i].parent = &dev->sriov.alias_guid; |
| 660 | 875 | dev->sriov.alias_guid.ports_guid[i].port = i; |
| 661 | − if (mlx4_ib_sm_guid_assign) | |
| 662 | − set_all_slaves_guids(dev, i); | |
| 663 | 876 | |
| 664 | 877 | snprintf(alias_wq_name, sizeof alias_wq_name, "alias_guid%d", i); |
| 665 | 878 | dev->sriov.alias_guid.ports_guid[i].wq = |
| @@ -1430,6 +1430,10 @@ static int mlx4_ib_alloc_pv_bufs(struct mlx4_ib_demux_pv_ctx *ctx, · 1429 unmodified lines | ||
| 1430 | 1430 | tun_qp->ring[i].addr, |
| 1431 | 1431 | rx_buf_size, |
| 1432 | 1432 | DMA_FROM_DEVICE); |
| 1433 | + if (ib_dma_mapping_error(ctx->ib_dev, tun_qp->ring[i].map)) { | |
| 1434 | + kfree(tun_qp->ring[i].addr); | |
| 1435 | + goto err; | |
| 1436 | + } | |
| 1433 | 1437 | } |
| 1434 | 1438 | |
| 1435 | 1439 | for (i = 0; i < MLX4_NUM_TUNNEL_BUFS; i++) { |
| @@ -1442,6 +1446,11 @@ static int mlx4_ib_alloc_pv_bufs(struct mlx4_ib_demux_pv_ctx *ctx, · 6 unmodified lines | ||
| 1442 | 1446 | tun_qp->tx_ring[i].buf.addr, |
| 1443 | 1447 | tx_buf_size, |
| 1444 | 1448 | DMA_TO_DEVICE); |
| 1449 | + if (ib_dma_mapping_error(ctx->ib_dev, | |
| 1450 | + tun_qp->tx_ring[i].buf.map)) { | |
| 1451 | + kfree(tun_qp->tx_ring[i].buf.addr); | |
| 1452 | + goto tx_err; | |
| 1453 | + } | |
| 1445 | 1454 | tun_qp->tx_ring[i].ah = NULL; |
| 1446 | 1455 | } |
| 1447 | 1456 | spin_lock_init(&tun_qp->tx_lock); |
| @@ -66,9 +66,9 @@ MODULE_DESCRIPTION("Mellanox ConnectX HCA InfiniBand driver"); · 65 unmodified lines | ||
| 66 | 66 | MODULE_LICENSE("Dual BSD/GPL"); |
| 67 | 67 | MODULE_VERSION(DRV_VERSION); |
| 68 | 68 | |
| 69 | −int mlx4_ib_sm_guid_assign = 1; | |
| 69 | +int mlx4_ib_sm_guid_assign = 0; | |
| 70 | 70 | module_param_named(sm_guid_assign, mlx4_ib_sm_guid_assign, int, 0444); |
| 71 | −MODULE_PARM_DESC(sm_guid_assign, "Enable SM alias_GUID assignment if sm_guid_assign > 0 (Default: 1)"); | |
| 71 | +MODULE_PARM_DESC(sm_guid_assign, "Enable SM alias_GUID assignment if sm_guid_assign > 0 (Default: 0)"); | |
| 72 | 72 | |
| 73 | 73 | static const char mlx4_ib_version[] = |
| 74 | 74 | DRV_NAME ": Mellanox ConnectX InfiniBand driver v" |
| @@ -2791,9 +2791,31 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr, · 2716 unmodified lines | ||
| 2791 | 2791 | case MLX4_DEV_EVENT_SLAVE_INIT: |
| 2792 | 2792 | /* here, p is the slave id */ |
| 2793 | 2793 | do_slave_init(ibdev, p, 1); |
| 2794 | + if (mlx4_is_master(dev)) { | |
| 2795 | + int i; | |
| 2796 | + | |
| 2797 | + for (i = 1; i <= ibdev->num_ports; i++) { | |
| 2798 | + if (rdma_port_get_link_layer(&ibdev->ib_dev, i) | |
| 2799 | + == IB_LINK_LAYER_INFINIBAND) | |
| 2800 | + mlx4_ib_slave_alias_guid_event(ibdev, | |
| 2801 | + p, i, | |
| 2802 | + 1); | |
| 2803 | + } | |
| 2804 | + } | |
| 2794 | 2805 | return; |
| 2795 | 2806 | |
| 2796 | 2807 | case MLX4_DEV_EVENT_SLAVE_SHUTDOWN: |
| 2808 | + if (mlx4_is_master(dev)) { | |
| 2809 | + int i; | |
| 2810 | + | |
| 2811 | + for (i = 1; i <= ibdev->num_ports; i++) { | |
| 2812 | + if (rdma_port_get_link_layer(&ibdev->ib_dev, i) | |
| 2813 | + == IB_LINK_LAYER_INFINIBAND) | |
| 2814 | + mlx4_ib_slave_alias_guid_event(ibdev, | |
| 2815 | + p, i, | |
| 2816 | + 0); | |
| 2817 | + } | |
| 2818 | + } | |
| 2797 | 2819 | /* here, p is the slave id */ |
| 2798 | 2820 | do_slave_init(ibdev, p, 0); |
| 2799 | 2821 | return; |
| @@ -342,14 +342,9 @@ struct mlx4_ib_ah { · 341 unmodified lines | ||
| 342 | 342 | enum mlx4_guid_alias_rec_status { |
| 343 | 343 | MLX4_GUID_INFO_STATUS_IDLE, |
| 344 | 344 | MLX4_GUID_INFO_STATUS_SET, |
| 345 | − MLX4_GUID_INFO_STATUS_PENDING, | |
| 346 | 345 | }; |
| 347 | 346 | |
| 348 | −enum mlx4_guid_alias_rec_ownership { | |
| 349 | − MLX4_GUID_DRIVER_ASSIGN, | |
| 350 | − MLX4_GUID_SYSADMIN_ASSIGN, | |
| 351 | − MLX4_GUID_NONE_ASSIGN, /*init state of each record*/ | |
| 352 | −}; | |
| 347 | +#define GUID_STATE_NEED_PORT_INIT 0x01 | |
| 353 | 348 | |
| 354 | 349 | enum mlx4_guid_alias_rec_method { |
| 355 | 350 | MLX4_GUID_INFO_RECORD_SET = IB_MGMT_METHOD_SET, |
| @@ -360,8 +355,8 @@ struct mlx4_sriov_alias_guid_info_rec_det { · 4 unmodified lines | ||
| 360 | 355 | u8 all_recs[GUID_REC_SIZE * NUM_ALIAS_GUID_IN_REC]; |
| 361 | 356 | ib_sa_comp_mask guid_indexes; /*indicates what from the 8 records are valid*/ |
| 362 | 357 | enum mlx4_guid_alias_rec_status status; /*indicates the administraively status of the record.*/ |
| 363 | − u8 method; /*set or delete*/ | |
| 364 | − enum mlx4_guid_alias_rec_ownership ownership; /*indicates who assign that alias_guid record*/ | |
| 358 | + unsigned int guids_retry_schedule[NUM_ALIAS_GUID_IN_REC]; | |
| 359 | + u64 time_to_run; | |
| 365 | 360 | }; |
| 366 | 361 | |
| 367 | 362 | struct mlx4_sriov_alias_guid_port_rec_det { |
| @@ -369,6 +364,7 @@ struct mlx4_sriov_alias_guid_port_rec_det { · 1 unmodified line | ||
| 369 | 364 | struct workqueue_struct *wq; |
| 370 | 365 | struct delayed_work alias_guid_work; |
| 371 | 366 | u8 port; |
| 367 | + u32 state_flags; | |
| 372 | 368 | struct mlx4_sriov_alias_guid *parent; |
| 373 | 369 | struct list_head cb_list; |
| 374 | 370 | }; |
| @@ -802,6 +798,8 @@ int add_sysfs_port_mcg_attr(struct mlx4_ib_dev *device, int port_num, · 427 unmodified lines | ||
| 802 | 798 | void del_sysfs_port_mcg_attr(struct mlx4_ib_dev *device, int port_num, |
| 803 | 799 | struct attribute *attr); |
| 804 | 800 | ib_sa_comp_mask mlx4_ib_get_aguid_comp_mask_from_ix(int index); |
| 801 | +void mlx4_ib_slave_alias_guid_event(struct mlx4_ib_dev *dev, int slave, | |
| 802 | + int port, int slave_init); | |
| 805 | 803 | |
| 806 | 804 | int mlx4_ib_device_register_sysfs(struct mlx4_ib_dev *device) ; |
| 807 | 805 | |
| @@ -566,6 +566,10 @@ static int alloc_proxy_bufs(struct ib_device *dev, struct mlx4_ib_qp *qp) · 565 unmodified lines | ||
| 566 | 566 | ib_dma_map_single(dev, qp->sqp_proxy_rcv[i].addr, |
| 567 | 567 | sizeof (struct mlx4_ib_proxy_sqp_hdr), |
| 568 | 568 | DMA_FROM_DEVICE); |
| 569 | + if (ib_dma_mapping_error(dev, qp->sqp_proxy_rcv[i].map)) { | |
| 570 | + kfree(qp->sqp_proxy_rcv[i].addr); | |
| 571 | + goto err; | |
| 572 | + } | |
| 569 | 573 | } |
| 570 | 574 | return 0; |
| 571 | 575 | |
| @@ -2605,8 +2609,7 @@ static int build_lso_seg(struct mlx4_wqe_lso_seg *wqe, struct ib_send_wr *wr, · 2033 unmodified lines | ||
| 2605 | 2609 | |
| 2606 | 2610 | memcpy(wqe->header, wr->wr.ud.header, wr->wr.ud.hlen); |
| 2607 | 2611 | |
| 2608 | − *lso_hdr_sz = cpu_to_be32((wr->wr.ud.mss - wr->wr.ud.hlen) << 16 | | |
| 2609 | − wr->wr.ud.hlen); | |
| 2612 | + *lso_hdr_sz = cpu_to_be32(wr->wr.ud.mss << 16 | wr->wr.ud.hlen); | |
| 2610 | 2613 | *lso_seg_len = halign; |
| 2611 | 2614 | return 0; |
| 2612 | 2615 | } |
| @@ -46,21 +46,17 @@ · 45 unmodified lines | ||
| 46 | 46 | static ssize_t show_admin_alias_guid(struct device *dev, |
| 47 | 47 | struct device_attribute *attr, char *buf) |
| 48 | 48 | { |
| 49 | − int record_num;/*0-15*/ | |
| 50 | − int guid_index_in_rec; /*0 - 7*/ | |
| 51 | 49 | struct mlx4_ib_iov_sysfs_attr *mlx4_ib_iov_dentry = |
| 52 | 50 | container_of(attr, struct mlx4_ib_iov_sysfs_attr, dentry); |
| 53 | 51 | struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx; |
| 54 | 52 | struct mlx4_ib_dev *mdev = port->dev; |
| 53 | + __be64 sysadmin_ag_val; | |
| 55 | 54 | |
| 56 | − record_num = mlx4_ib_iov_dentry->entry_num / 8 ; | |
| 57 | − guid_index_in_rec = mlx4_ib_iov_dentry->entry_num % 8 ; | |
| 55 | + sysadmin_ag_val = mlx4_get_admin_guid(mdev->dev, | |
| 56 | + mlx4_ib_iov_dentry->entry_num, | |
| 57 | + port->num); | |
| 58 | 58 | |
| 59 | − return sprintf(buf, "%llx\n", | |
| 60 | − be64_to_cpu(*(__be64 *)&mdev->sriov.alias_guid. | |
| 61 | − ports_guid[port->num - 1]. | |
| 62 | − all_rec_per_port[record_num]. | |
| 63 | − all_recs[8 * guid_index_in_rec])); | |
| 59 | + return sprintf(buf, "%llx\n", be64_to_cpu(sysadmin_ag_val)); | |
| 64 | 60 | } |
| 65 | 61 | |
| 66 | 62 | /* store_admin_alias_guid stores the (new) administratively assigned value of that GUID. |
| @@ -80,6 +76,7 @@ static ssize_t store_admin_alias_guid(struct device *dev, · 13 unmodified lines | ||
| 80 | 76 | struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx; |
| 81 | 77 | struct mlx4_ib_dev *mdev = port->dev; |
| 82 | 78 | u64 sysadmin_ag_val; |
| 79 | + unsigned long flags; | |
| 83 | 80 | |
| 84 | 81 | record_num = mlx4_ib_iov_dentry->entry_num / 8; |
| 85 | 82 | guid_index_in_rec = mlx4_ib_iov_dentry->entry_num % 8; |
| @@ -87,6 +84,7 @@ static ssize_t store_admin_alias_guid(struct device *dev, · 1 unmodified line | ||
| 87 | 84 | pr_err("GUID 0 block 0 is RO\n"); |
| 88 | 85 | return count; |
| 89 | 86 | } |
| 87 | + spin_lock_irqsave(&mdev->sriov.alias_guid.ag_work_lock, flags); | |
| 90 | 88 | sscanf(buf, "%llx", &sysadmin_ag_val); |
| 91 | 89 | *(__be64 *)&mdev->sriov.alias_guid.ports_guid[port->num - 1]. |
| 92 | 90 | all_rec_per_port[record_num]. |
| @@ -96,33 +94,15 @@ static ssize_t store_admin_alias_guid(struct device *dev, · 3 unmodified lines | ||
| 96 | 94 | /* Change the state to be pending for update */ |
| 97 | 95 | mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].status |
| 98 | 96 | = MLX4_GUID_INFO_STATUS_IDLE ; |
| 99 | − | |
| 100 | − mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].method | |
| 101 | − = MLX4_GUID_INFO_RECORD_SET; | |
| 102 | − | |
| 103 | − switch (sysadmin_ag_val) { | |
| 104 | − case MLX4_GUID_FOR_DELETE_VAL: | |
| 105 | − mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].method | |
| 106 | − = MLX4_GUID_INFO_RECORD_DELETE; | |
| 107 | − mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].ownership | |
| 108 | − = MLX4_GUID_SYSADMIN_ASSIGN; | |
| 109 | − break; | |
| 110 | − /* The sysadmin requests the SM to re-assign */ | |
| 111 | − case MLX4_NOT_SET_GUID: | |
| 112 | − mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].ownership | |
| 113 | − = MLX4_GUID_DRIVER_ASSIGN; | |
| 114 | − break; | |
| 115 | − /* The sysadmin requests a specific value.*/ | |
| 116 | − default: | |
| 117 | − mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].ownership | |
| 118 | − = MLX4_GUID_SYSADMIN_ASSIGN; | |
| 119 | − break; | |
| 120 | − } | |
| 97 | + mlx4_set_admin_guid(mdev->dev, cpu_to_be64(sysadmin_ag_val), | |
| 98 | + mlx4_ib_iov_dentry->entry_num, | |
| 99 | + port->num); | |
| 121 | 100 | |
| 122 | 101 | /* set the record index */ |
| 123 | 102 | mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].guid_indexes |
| 124 | − = mlx4_ib_get_aguid_comp_mask_from_ix(guid_index_in_rec); | |
| 103 | + |= mlx4_ib_get_aguid_comp_mask_from_ix(guid_index_in_rec); | |
| 125 | 104 | |
| 105 | + spin_unlock_irqrestore(&mdev->sriov.alias_guid.ag_work_lock, flags); | |
| 126 | 106 | mlx4_ib_init_alias_guid_work(mdev, port->num - 1); |
| 127 | 107 | |
| 128 | 108 | return count; |
| @@ -87,7 +87,6 @@ enum { · 86 unmodified lines | ||
| 87 | 87 | IPOIB_FLAG_ADMIN_UP = 2, |
| 88 | 88 | IPOIB_PKEY_ASSIGNED = 3, |
| 89 | 89 | IPOIB_FLAG_SUBINTERFACE = 5, |
| 90 | − IPOIB_MCAST_RUN = 6, | |
| 91 | 90 | IPOIB_STOP_REAPER = 7, |
| 92 | 91 | IPOIB_FLAG_ADMIN_CM = 9, |
| 93 | 92 | IPOIB_FLAG_UMCAST = 10, |
| @@ -98,9 +97,15 @@ enum { · 4 unmodified lines | ||
| 98 | 97 | |
| 99 | 98 | IPOIB_MCAST_FLAG_FOUND = 0, /* used in set_multicast_list */ |
| 100 | 99 | IPOIB_MCAST_FLAG_SENDONLY = 1, |
| 101 | − IPOIB_MCAST_FLAG_BUSY = 2, /* joining or already joined */ | |
| 100 | + /* | |
| 101 | + * For IPOIB_MCAST_FLAG_BUSY | |
| 102 | + * When set, in flight join and mcast->mc is unreliable | |
| 103 | + * When clear and mcast->mc IS_ERR_OR_NULL, need to restart or | |
| 104 | + * haven't started yet | |
| 105 | + * When clear and mcast->mc is valid pointer, join was successful | |
| 106 | + */ | |
| 107 | + IPOIB_MCAST_FLAG_BUSY = 2, | |
| 102 | 108 | IPOIB_MCAST_FLAG_ATTACHED = 3, |
| 103 | − IPOIB_MCAST_JOIN_STARTED = 4, | |
| 104 | 109 | |
| 105 | 110 | MAX_SEND_CQE = 16, |
| 106 | 111 | IPOIB_CM_COPYBREAK = 256, |
| @@ -148,6 +153,7 @@ struct ipoib_mcast { · 41 unmodified lines | ||
| 148 | 153 | |
| 149 | 154 | unsigned long created; |
| 150 | 155 | unsigned long backoff; |
| 156 | + unsigned long delay_until; | |
| 151 | 157 | |
| 152 | 158 | unsigned long flags; |
| 153 | 159 | unsigned char logcount; |
| @@ -292,6 +298,11 @@ struct ipoib_neigh_table { · 138 unmodified lines | ||
| 292 | 298 | struct completion deleted; |
| 293 | 299 | }; |
| 294 | 300 | |
| 301 | +struct ipoib_qp_state_validate { | |
| 302 | + struct work_struct work; | |
| 303 | + struct ipoib_dev_priv *priv; | |
| 304 | +}; | |
| 305 | + | |
| 295 | 306 | /* |
| 296 | 307 | * Device private locking: network stack tx_lock protects members used |
| 297 | 308 | * in TX fast path, lock protects everything else. lock nests inside |
| @@ -317,6 +328,7 @@ struct ipoib_dev_priv { · 19 unmodified lines | ||
| 317 | 328 | struct list_head multicast_list; |
| 318 | 329 | struct rb_root multicast_tree; |
| 319 | 330 | |
| 331 | + struct workqueue_struct *wq; | |
| 320 | 332 | struct delayed_work mcast_task; |
| 321 | 333 | struct work_struct carrier_on_task; |
| 322 | 334 | struct work_struct flush_light; |
| @@ -426,11 +438,6 @@ struct ipoib_neigh { · 103 unmodified lines | ||
| 426 | 438 | #define IPOIB_UD_MTU(ib_mtu) (ib_mtu - IPOIB_ENCAP_LEN) |
| 427 | 439 | #define IPOIB_UD_BUF_SIZE(ib_mtu) (ib_mtu + IB_GRH_BYTES) |
| 428 | 440 | |
| 429 | −static inline int ipoib_ud_need_sg(unsigned int ib_mtu) | |
| 430 | −{ | |
| 431 | − return IPOIB_UD_BUF_SIZE(ib_mtu) > PAGE_SIZE; | |
| 432 | −} | |
| 433 | − | |
| 434 | 441 | void ipoib_neigh_dtor(struct ipoib_neigh *neigh); |
| 435 | 442 | static inline void ipoib_neigh_put(struct ipoib_neigh *neigh) |
| 436 | 443 | { |
| @@ -477,10 +484,10 @@ void ipoib_ib_dev_flush_heavy(struct work_struct *work); · 40 unmodified lines | ||
| 477 | 484 | void ipoib_pkey_event(struct work_struct *work); |
| 478 | 485 | void ipoib_ib_dev_cleanup(struct net_device *dev); |
| 479 | 486 | |
| 480 | −int ipoib_ib_dev_open(struct net_device *dev, int flush); | |
| 487 | +int ipoib_ib_dev_open(struct net_device *dev); | |
| 481 | 488 | int ipoib_ib_dev_up(struct net_device *dev); |
| 482 | −int ipoib_ib_dev_down(struct net_device *dev, int flush); | |
| 483 | −int ipoib_ib_dev_stop(struct net_device *dev, int flush); | |
| 489 | +int ipoib_ib_dev_down(struct net_device *dev); | |
| 490 | +int ipoib_ib_dev_stop(struct net_device *dev); | |
| 484 | 491 | void ipoib_pkey_dev_check_presence(struct net_device *dev); |
| 485 | 492 | |
| 486 | 493 | int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port); |
| @@ -492,7 +499,7 @@ void ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb); · 5 unmodified lines | ||
| 492 | 499 | |
| 493 | 500 | void ipoib_mcast_restart_task(struct work_struct *work); |
| 494 | 501 | int ipoib_mcast_start_thread(struct net_device *dev); |
| 495 | −int ipoib_mcast_stop_thread(struct net_device *dev, int flush); | |
| 502 | +int ipoib_mcast_stop_thread(struct net_device *dev); | |
| 496 | 503 | |
| 497 | 504 | void ipoib_mcast_dev_down(struct net_device *dev); |
| 498 | 505 | void ipoib_mcast_dev_flush(struct net_device *dev); |
| @@ -474,7 +474,7 @@ static int ipoib_cm_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *even · 473 unmodified lines | ||
| 474 | 474 | } |
| 475 | 475 | |
| 476 | 476 | spin_lock_irq(&priv->lock); |
| 477 | − queue_delayed_work(ipoib_workqueue, | |
| 477 | + queue_delayed_work(priv->wq, | |
| 478 | 478 | &priv->cm.stale_task, IPOIB_CM_RX_DELAY); |
| 479 | 479 | /* Add this entry to passive ids list head, but do not re-add it |
| 480 | 480 | * if IB_EVENT_QP_LAST_WQE_REACHED has moved it to flush list. */ |
| @@ -576,7 +576,7 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) · 95 unmodified lines | ||
| 576 | 576 | spin_lock_irqsave(&priv->lock, flags); |
| 577 | 577 | list_splice_init(&priv->cm.rx_drain_list, &priv->cm.rx_reap_list); |
| 578 | 578 | ipoib_cm_start_rx_drain(priv); |
| 579 | − queue_work(ipoib_workqueue, &priv->cm.rx_reap_task); | |
| 579 | + queue_work(priv->wq, &priv->cm.rx_reap_task); | |
| 580 | 580 | spin_unlock_irqrestore(&priv->lock, flags); |
| 581 | 581 | } else |
| 582 | 582 | ipoib_warn(priv, "cm recv completion event with wrid %d (> %d)\n", |
| @@ -603,7 +603,7 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) · 20 unmodified lines | ||
| 603 | 603 | spin_lock_irqsave(&priv->lock, flags); |
| 604 | 604 | list_move(&p->list, &priv->cm.rx_reap_list); |
| 605 | 605 | spin_unlock_irqrestore(&priv->lock, flags); |
| 606 | − queue_work(ipoib_workqueue, &priv->cm.rx_reap_task); | |
| 606 | + queue_work(priv->wq, &priv->cm.rx_reap_task); | |
| 607 | 607 | } |
| 608 | 608 | return; |
| 609 | 609 | } |
| @@ -827,7 +827,7 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) · 217 unmodified lines | ||
| 827 | 827 | |
| 828 | 828 | if (test_and_clear_bit(IPOIB_FLAG_INITIALIZED, &tx->flags)) { |
| 829 | 829 | list_move(&tx->list, &priv->cm.reap_list); |
| 830 | − queue_work(ipoib_workqueue, &priv->cm.reap_task); | |
| 830 | + queue_work(priv->wq, &priv->cm.reap_task); | |
| 831 | 831 | } |
| 832 | 832 | |
| 833 | 833 | clear_bit(IPOIB_FLAG_OPER_UP, &tx->flags); |
| @@ -1255,7 +1255,7 @@ static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id, · 421 unmodified lines | ||
| 1255 | 1255 | |
| 1256 | 1256 | if (test_and_clear_bit(IPOIB_FLAG_INITIALIZED, &tx->flags)) { |
| 1257 | 1257 | list_move(&tx->list, &priv->cm.reap_list); |
| 1258 | − queue_work(ipoib_workqueue, &priv->cm.reap_task); | |
| 1258 | + queue_work(priv->wq, &priv->cm.reap_task); | |
| 1259 | 1259 | } |
| 1260 | 1260 | |
| 1261 | 1261 | spin_unlock_irqrestore(&priv->lock, flags); |
| @@ -1284,7 +1284,7 @@ struct ipoib_cm_tx *ipoib_cm_create_tx(struct net_device *dev, struct ipoib_path · 22 unmodified lines | ||
| 1284 | 1284 | tx->dev = dev; |
| 1285 | 1285 | list_add(&tx->list, &priv->cm.start_list); |
| 1286 | 1286 | set_bit(IPOIB_FLAG_INITIALIZED, &tx->flags); |
| 1287 | − queue_work(ipoib_workqueue, &priv->cm.start_task); | |
| 1287 | + queue_work(priv->wq, &priv->cm.start_task); | |
| 1288 | 1288 | return tx; |
| 1289 | 1289 | } |
| 1290 | 1290 | |
| @@ -1295,7 +1295,7 @@ void ipoib_cm_destroy_tx(struct ipoib_cm_tx *tx) · 4 unmodified lines | ||
| 1295 | 1295 | if (test_and_clear_bit(IPOIB_FLAG_INITIALIZED, &tx->flags)) { |
| 1296 | 1296 | spin_lock_irqsave(&priv->lock, flags); |
| 1297 | 1297 | list_move(&tx->list, &priv->cm.reap_list); |
| 1298 | − queue_work(ipoib_workqueue, &priv->cm.reap_task); | |
| 1298 | + queue_work(priv->wq, &priv->cm.reap_task); | |
| 1299 | 1299 | ipoib_dbg(priv, "Reap connection for gid %pI6\n", |
| 1300 | 1300 | tx->neigh->daddr + 4); |
| 1301 | 1301 | tx->neigh = NULL; |
| @@ -1417,7 +1417,7 @@ void ipoib_cm_skb_too_long(struct net_device *dev, struct sk_buff *skb, · 115 unmodified lines | ||
| 1417 | 1417 | |
| 1418 | 1418 | skb_queue_tail(&priv->cm.skb_queue, skb); |
| 1419 | 1419 | if (e) |
| 1420 | − queue_work(ipoib_workqueue, &priv->cm.skb_task); | |
| 1420 | + queue_work(priv->wq, &priv->cm.skb_task); | |
| 1421 | 1421 | } |
| 1422 | 1422 | |
| 1423 | 1423 | static void ipoib_cm_rx_reap(struct work_struct *work) |
| @@ -1450,7 +1450,7 @@ static void ipoib_cm_stale_task(struct work_struct *work) · 26 unmodified lines | ||
| 1450 | 1450 | } |
| 1451 | 1451 | |
| 1452 | 1452 | if (!list_empty(&priv->cm.passive_ids)) |
| 1453 | − queue_delayed_work(ipoib_workqueue, | |
| 1453 | + queue_delayed_work(priv->wq, | |
| 1454 | 1454 | &priv->cm.stale_task, IPOIB_CM_RX_DELAY); |
| 1455 | 1455 | spin_unlock_irq(&priv->lock); |
| 1456 | 1456 | } |
| @@ -94,39 +94,9 @@ void ipoib_free_ah(struct kref *kref) · 93 unmodified lines | ||
| 94 | 94 | static void ipoib_ud_dma_unmap_rx(struct ipoib_dev_priv *priv, |
| 95 | 95 | u64 mapping[IPOIB_UD_RX_SG]) |
| 96 | 96 | { |
| 97 | − if (ipoib_ud_need_sg(priv->max_ib_mtu)) { | |
| 98 | − ib_dma_unmap_single(priv->ca, mapping[0], IPOIB_UD_HEAD_SIZE, | |
| 99 | − DMA_FROM_DEVICE); | |
| 100 | − ib_dma_unmap_page(priv->ca, mapping[1], PAGE_SIZE, | |
| 101 | − DMA_FROM_DEVICE); | |
| 102 | − } else | |
| 103 | − ib_dma_unmap_single(priv->ca, mapping[0], | |
| 104 | − IPOIB_UD_BUF_SIZE(priv->max_ib_mtu), | |
| 105 | − DMA_FROM_DEVICE); | |
| 106 | −} | |
| 107 | − | |
| 108 | −static void ipoib_ud_skb_put_frags(struct ipoib_dev_priv *priv, | |
| 109 | − struct sk_buff *skb, | |
| 110 | − unsigned int length) | |
| 111 | −{ | |
| 112 | − if (ipoib_ud_need_sg(priv->max_ib_mtu)) { | |
| 113 | − skb_frag_t *frag = &skb_shinfo(skb)->frags[0]; | |
| 114 | − unsigned int size; | |
| 115 | − /* | |
| 116 | − * There is only two buffers needed for max_payload = 4K, | |
| 117 | − * first buf size is IPOIB_UD_HEAD_SIZE | |
| 118 | − */ | |
| 119 | − skb->tail += IPOIB_UD_HEAD_SIZE; | |
| 120 | − skb->len += length; | |
| 121 | − | |
| 122 | − size = length - IPOIB_UD_HEAD_SIZE; | |
| 123 | − | |
| 124 | − skb_frag_size_set(frag, size); | |
| 125 | − skb->data_len += size; | |
| 126 | − skb->truesize += PAGE_SIZE; | |
| 127 | − } else | |
| 128 | − skb_put(skb, length); | |
| 129 | − | |
| 97 | + ib_dma_unmap_single(priv->ca, mapping[0], | |
| 98 | + IPOIB_UD_BUF_SIZE(priv->max_ib_mtu), | |
| 99 | + DMA_FROM_DEVICE); | |
| 130 | 100 | } |
| 131 | 101 | |
| 132 | 102 | static int ipoib_ib_post_receive(struct net_device *dev, int id) |
| @@ -156,18 +126,11 @@ static struct sk_buff *ipoib_alloc_rx_skb(struct net_device *dev, int id) · 23 unmodified lines | ||
| 156 | 126 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
| 157 | 127 | struct sk_buff *skb; |
| 158 | 128 | int buf_size; |
| 159 | − int tailroom; | |
| 160 | 129 | u64 *mapping; |
| 161 | 130 | |
| 162 | − if (ipoib_ud_need_sg(priv->max_ib_mtu)) { | |
| 163 | − buf_size = IPOIB_UD_HEAD_SIZE; | |
| 164 | − tailroom = 128; /* reserve some tailroom for IP/TCP headers */ | |
| 165 | − } else { | |
| 166 | − buf_size = IPOIB_UD_BUF_SIZE(priv->max_ib_mtu); | |
| 167 | − tailroom = 0; | |
| 168 | − } | |
| 131 | + buf_size = IPOIB_UD_BUF_SIZE(priv->max_ib_mtu); | |
| 169 | 132 | |
| 170 | − skb = dev_alloc_skb(buf_size + tailroom + 4); | |
| 133 | + skb = dev_alloc_skb(buf_size + IPOIB_ENCAP_LEN); | |
| 171 | 134 | if (unlikely(!skb)) |
| 172 | 135 | return NULL; |
| 173 | 136 | |
| @@ -184,23 +147,8 @@ static struct sk_buff *ipoib_alloc_rx_skb(struct net_device *dev, int id) · 10 unmodified lines | ||
| 184 | 147 | if (unlikely(ib_dma_mapping_error(priv->ca, mapping[0]))) |
| 185 | 148 | goto error; |
| 186 | 149 | |
| 187 | − if (ipoib_ud_need_sg(priv->max_ib_mtu)) { | |
| 188 | − struct page *page = alloc_page(GFP_ATOMIC); | |
| 189 | − if (!page) | |
| 190 | − goto partial_error; | |
| 191 | − skb_fill_page_desc(skb, 0, page, 0, PAGE_SIZE); | |
| 192 | − mapping[1] = | |
| 193 | − ib_dma_map_page(priv->ca, page, | |
| 194 | − 0, PAGE_SIZE, DMA_FROM_DEVICE); | |
| 195 | − if (unlikely(ib_dma_mapping_error(priv->ca, mapping[1]))) | |
| 196 | − goto partial_error; | |
| 197 | − } | |
| 198 | − | |
| 199 | 150 | priv->rx_ring[id].skb = skb; |
| 200 | 151 | return skb; |
| 201 | − | |
| 202 | −partial_error: | |
| 203 | − ib_dma_unmap_single(priv->ca, mapping[0], buf_size, DMA_FROM_DEVICE); | |
| 204 | 152 | error: |
| 205 | 153 | dev_kfree_skb_any(skb); |
| 206 | 154 | return NULL; |
| @@ -278,7 +226,8 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) · 71 unmodified lines | ||
| 278 | 226 | wc->byte_len, wc->slid); |
| 279 | 227 | |
| 280 | 228 | ipoib_ud_dma_unmap_rx(priv, mapping); |
| 281 | − ipoib_ud_skb_put_frags(priv, skb, wc->byte_len); | |
| 229 | + | |
| 230 | + skb_put(skb, wc->byte_len); | |
| 282 | 231 | |
| 283 | 232 | /* First byte of dgid signals multicast when 0xff */ |
| 284 | 233 | dgid = &((struct ib_grh *)skb->data)->dgid; |
| @@ -296,6 +245,8 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) · 11 unmodified lines | ||
| 296 | 245 | skb_reset_mac_header(skb); |
| 297 | 246 | skb_pull(skb, IPOIB_ENCAP_LEN); |
| 298 | 247 | |
| 248 | + skb->truesize = SKB_TRUESIZE(skb->len); | |
| 249 | + | |
| 299 | 250 | ++dev->stats.rx_packets; |
| 300 | 251 | dev->stats.rx_bytes += skb->len; |
| 301 | 252 | |
| @@ -376,6 +327,51 @@ static void ipoib_dma_unmap_tx(struct ib_device *ca, · 74 unmodified lines | ||
| 376 | 327 | } |
| 377 | 328 | } |
| 378 | 329 | |
| 330 | +/* | |
| 331 | + * As the result of a completion error the QP Can be transferred to SQE states. | |
| 332 | + * The function checks if the (send)QP is in SQE state and | |
| 333 | + * moves it back to RTS state, that in order to have it functional again. | |
| 334 | + */ | |
| 335 | +static void ipoib_qp_state_validate_work(struct work_struct *work) | |
| 336 | +{ | |
| 337 | + struct ipoib_qp_state_validate *qp_work = | |
| 338 | + container_of(work, struct ipoib_qp_state_validate, work); | |
| 339 | + | |
| 340 | + struct ipoib_dev_priv *priv = qp_work->priv; | |
| 341 | + struct ib_qp_attr qp_attr; | |
| 342 | + struct ib_qp_init_attr query_init_attr; | |
| 343 | + int ret; | |
| 344 | + | |
| 345 | + ret = ib_query_qp(priv->qp, &qp_attr, IB_QP_STATE, &query_init_attr); | |
| 346 | + if (ret) { | |
| 347 | + ipoib_warn(priv, "%s: Failed to query QP ret: %d\n", | |
| 348 | + __func__, ret); | |
| 349 | + goto free_res; | |
| 350 | + } | |
| 351 | + pr_info("%s: QP: 0x%x is in state: %d\n", | |
| 352 | + __func__, priv->qp->qp_num, qp_attr.qp_state); | |
| 353 | + | |
| 354 | + /* currently support only in SQE->RTS transition*/ | |
| 355 | + if (qp_attr.qp_state == IB_QPS_SQE) { | |
| 356 | + qp_attr.qp_state = IB_QPS_RTS; | |
| 357 | + | |
| 358 | + ret = ib_modify_qp(priv->qp, &qp_attr, IB_QP_STATE); | |
| 359 | + if (ret) { | |
| 360 | + pr_warn("failed(%d) modify QP:0x%x SQE->RTS\n", | |
| 361 | + ret, priv->qp->qp_num); | |
| 362 | + goto free_res; | |
| 363 | + } | |
| 364 | + pr_info("%s: QP: 0x%x moved from IB_QPS_SQE to IB_QPS_RTS\n", | |
| 365 | + __func__, priv->qp->qp_num); | |
| 366 | + } else { | |
| 367 | + pr_warn("QP (%d) will stay in state: %d\n", | |
| 368 | + priv->qp->qp_num, qp_attr.qp_state); | |
| 369 | + } | |
| 370 | + | |
| 371 | +free_res: | |
| 372 | + kfree(qp_work); | |
| 373 | +} | |
| 374 | + | |
| 379 | 375 | static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) |
| 380 | 376 | { |
| 381 | 377 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
| @@ -407,10 +403,22 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) · 25 unmodified lines | ||
| 407 | 403 | netif_wake_queue(dev); |
| 408 | 404 | |
| 409 | 405 | if (wc->status != IB_WC_SUCCESS && |
| 410 | − wc->status != IB_WC_WR_FLUSH_ERR) | |
| 406 | + wc->status != IB_WC_WR_FLUSH_ERR) { | |
| 407 | + struct ipoib_qp_state_validate *qp_work; | |
| 411 | 408 | ipoib_warn(priv, "failed send event " |
| 412 | 409 | "(status=%d, wrid=%d vend_err %x)\n", |
| 413 | 410 | wc->status, wr_id, wc->vendor_err); |
| 411 | + qp_work = kzalloc(sizeof(*qp_work), GFP_ATOMIC); | |
| 412 | + if (!qp_work) { | |
| 413 | + ipoib_warn(priv, "%s Failed alloc ipoib_qp_state_validate for qp: 0x%x\n", | |
| 414 | + __func__, priv->qp->qp_num); | |
| 415 | + return; | |
| 416 | + } | |
| 417 | + | |
| 418 | + INIT_WORK(&qp_work->work, ipoib_qp_state_validate_work); | |
| 419 | + qp_work->priv = priv; | |
| 420 | + queue_work(priv->wq, &qp_work->work); | |
| 421 | + } | |
| 414 | 422 | } |
| 415 | 423 | |
| 416 | 424 | static int poll_tx(struct ipoib_dev_priv *priv) |
| @@ -655,16 +663,33 @@ void ipoib_reap_ah(struct work_struct *work) · 238 unmodified lines | ||
| 655 | 663 | __ipoib_reap_ah(dev); |
| 656 | 664 | |
| 657 | 665 | if (!test_bit(IPOIB_STOP_REAPER, &priv->flags)) |
| 658 | − queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task, | |
| 666 | + queue_delayed_work(priv->wq, &priv->ah_reap_task, | |
| 659 | 667 | round_jiffies_relative(HZ)); |
| 660 | 668 | } |
| 661 | 669 | |
| 670 | +static void ipoib_flush_ah(struct net_device *dev) | |
| 671 | +{ | |
| 672 | + struct ipoib_dev_priv *priv = netdev_priv(dev); | |
| 673 | + | |
| 674 | + cancel_delayed_work(&priv->ah_reap_task); | |
| 675 | + flush_workqueue(priv->wq); | |
| 676 | + ipoib_reap_ah(&priv->ah_reap_task.work); | |
| 677 | +} | |
| 678 | + | |
| 679 | +static void ipoib_stop_ah(struct net_device *dev) | |
| 680 | +{ | |
| 681 | + struct ipoib_dev_priv *priv = netdev_priv(dev); | |
| 682 | + | |
| 683 | + set_bit(IPOIB_STOP_REAPER, &priv->flags); | |
| 684 | + ipoib_flush_ah(dev); | |
| 685 | +} | |
| 686 | + | |
| 662 | 687 | static void ipoib_ib_tx_timer_func(unsigned long ctx) |
| 663 | 688 | { |
| 664 | 689 | drain_tx_cq((struct net_device *)ctx); |
| 665 | 690 | } |
| 666 | 691 | |
| 667 | −int ipoib_ib_dev_open(struct net_device *dev, int flush) | |
| 692 | +int ipoib_ib_dev_open(struct net_device *dev) | |
| 668 | 693 | { |
| 669 | 694 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
| 670 | 695 | int ret; |
| @@ -696,7 +721,7 @@ int ipoib_ib_dev_open(struct net_device *dev, int flush) · 25 unmodified lines | ||
| 696 | 721 | } |
| 697 | 722 | |
| 698 | 723 | clear_bit(IPOIB_STOP_REAPER, &priv->flags); |
| 699 | − queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task, | |
| 724 | + queue_delayed_work(priv->wq, &priv->ah_reap_task, | |
| 700 | 725 | round_jiffies_relative(HZ)); |
| 701 | 726 | |
| 702 | 727 | if (!test_and_set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags)) |
| @@ -706,7 +731,7 @@ int ipoib_ib_dev_open(struct net_device *dev, int flush) · 3 unmodified lines | ||
| 706 | 731 | dev_stop: |
| 707 | 732 | if (!test_and_set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags)) |
| 708 | 733 | napi_enable(&priv->napi); |
| 709 | − ipoib_ib_dev_stop(dev, flush); | |
| 734 | + ipoib_ib_dev_stop(dev); | |
| 710 | 735 | return -1; |
| 711 | 736 | } |
| 712 | 737 | |
| @@ -738,7 +763,7 @@ int ipoib_ib_dev_up(struct net_device *dev) · 25 unmodified lines | ||
| 738 | 763 | return ipoib_mcast_start_thread(dev); |
| 739 | 764 | } |
| 740 | 765 | |
| 741 | −int ipoib_ib_dev_down(struct net_device *dev, int flush) | |
| 766 | +int ipoib_ib_dev_down(struct net_device *dev) | |
| 742 | 767 | { |
| 743 | 768 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
| 744 | 769 | |
| @@ -747,7 +772,7 @@ int ipoib_ib_dev_down(struct net_device *dev, int flush) · 2 unmodified lines | ||
| 747 | 772 | clear_bit(IPOIB_FLAG_OPER_UP, &priv->flags); |
| 748 | 773 | netif_carrier_off(dev); |
| 749 | 774 | |
| 750 | − ipoib_mcast_stop_thread(dev, flush); | |
| 775 | + ipoib_mcast_stop_thread(dev); | |
| 751 | 776 | ipoib_mcast_dev_flush(dev); |
| 752 | 777 | |
| 753 | 778 | ipoib_flush_paths(dev); |
| @@ -807,7 +832,7 @@ void ipoib_drain_cq(struct net_device *dev) · 53 unmodified lines | ||
| 807 | 832 | local_bh_enable(); |
| 808 | 833 | } |
| 809 | 834 | |
| 810 | −int ipoib_ib_dev_stop(struct net_device *dev, int flush) | |
| 835 | +int ipoib_ib_dev_stop(struct net_device *dev) | |
| 811 | 836 | { |
| 812 | 837 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
| 813 | 838 | struct ib_qp_attr qp_attr; |
| @@ -877,24 +902,7 @@ timeout: · 63 unmodified lines | ||
| 877 | 902 | if (ib_modify_qp(priv->qp, &qp_attr, IB_QP_STATE)) |
| 878 | 903 | ipoib_warn(priv, "Failed to modify QP to RESET state\n"); |
| 879 | 904 | |
| 880 | − /* Wait for all AHs to be reaped */ | |
| 881 | − set_bit(IPOIB_STOP_REAPER, &priv->flags); | |
| 882 | − cancel_delayed_work(&priv->ah_reap_task); | |
| 883 | − if (flush) | |
| 884 | − flush_workqueue(ipoib_workqueue); | |
| 885 | − | |
| 886 | − begin = jiffies; | |
| 887 | − | |
| 888 | − while (!list_empty(&priv->dead_ahs)) { | |
| 889 | − __ipoib_reap_ah(dev); | |
| 890 | − | |
| 891 | − if (time_after(jiffies, begin + HZ)) { | |
| 892 | − ipoib_warn(priv, "timing out; will leak address handles\n"); | |
| 893 | − break; | |
| 894 | − } | |
| 895 | − | |
| 896 | − msleep(1); | |
| 897 | − } | |
| 905 | + ipoib_flush_ah(dev); | |
| 898 | 906 | |
| 899 | 907 | ib_req_notify_cq(priv->recv_cq, IB_CQ_NEXT_COMP); |
| 900 | 908 | |
| @@ -918,7 +926,7 @@ int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port) · 17 unmodified lines | ||
| 918 | 926 | (unsigned long) dev); |
| 919 | 927 | |
| 920 | 928 | if (dev->flags & IFF_UP) { |
| 921 | − if (ipoib_ib_dev_open(dev, 1)) { | |
| 929 | + if (ipoib_ib_dev_open(dev)) { | |
| 922 | 930 | ipoib_transport_dev_cleanup(dev); |
| 923 | 931 | return -ENODEV; |
| 924 | 932 | } |
| @@ -1037,15 +1045,16 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, · 112 unmodified lines | ||
| 1037 | 1045 | if (level == IPOIB_FLUSH_LIGHT) { |
| 1038 | 1046 | ipoib_mark_paths_invalid(dev); |
| 1039 | 1047 | ipoib_mcast_dev_flush(dev); |
| 1048 | + ipoib_flush_ah(dev); | |
| 1040 | 1049 | } |
| 1041 | 1050 | |
| 1042 | 1051 | if (level >= IPOIB_FLUSH_NORMAL) |
| 1043 | − ipoib_ib_dev_down(dev, 0); | |
| 1052 | + ipoib_ib_dev_down(dev); | |
| 1044 | 1053 | |
| 1045 | 1054 | if (level == IPOIB_FLUSH_HEAVY) { |
| 1046 | 1055 | if (test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags)) |
| 1047 | − ipoib_ib_dev_stop(dev, 0); | |
| 1048 | − if (ipoib_ib_dev_open(dev, 0) != 0) | |
| 1056 | + ipoib_ib_dev_stop(dev); | |
| 1057 | + if (ipoib_ib_dev_open(dev) != 0) | |
| 1049 | 1058 | return; |
| 1050 | 1059 | if (netif_queue_stopped(dev)) |
| 1051 | 1060 | netif_start_queue(dev); |
| @@ -1097,9 +1106,17 @@ void ipoib_ib_dev_cleanup(struct net_device *dev) · 45 unmodified lines | ||
| 1097 | 1106 | */ |
| 1098 | 1107 | ipoib_flush_paths(dev); |
| 1099 | 1108 | |
| 1100 | − ipoib_mcast_stop_thread(dev, 1); | |
| 1109 | + ipoib_mcast_stop_thread(dev); | |
| 1101 | 1110 | ipoib_mcast_dev_flush(dev); |
| 1102 | 1111 | |
| 1112 | + /* | |
| 1113 | + * All of our ah references aren't free until after | |
| 1114 | + * ipoib_mcast_dev_flush(), ipoib_flush_paths, and | |
| 1115 | + * the neighbor garbage collection is stopped and reaped. | |
| 1116 | + * That should all be done now, so make a final ah flush. | |
| 1117 | + */ | |
| 1118 | + ipoib_stop_ah(dev); | |
| 1119 | + | |
| 1103 | 1120 | ipoib_transport_dev_cleanup(dev); |
| 1104 | 1121 | } |
| 1105 | 1122 | |
| @@ -108,7 +108,7 @@ int ipoib_open(struct net_device *dev) · 107 unmodified lines | ||
| 108 | 108 | |
| 109 | 109 | set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); |
| 110 | 110 | |
| 111 | − if (ipoib_ib_dev_open(dev, 1)) { | |
| 111 | + if (ipoib_ib_dev_open(dev)) { | |
| 112 | 112 | if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) |
| 113 | 113 | return 0; |
| 114 | 114 | goto err_disable; |
| @@ -139,7 +139,7 @@ int ipoib_open(struct net_device *dev) · 24 unmodified lines | ||
| 139 | 139 | return 0; |
| 140 | 140 | |
| 141 | 141 | err_stop: |
| 142 | − ipoib_ib_dev_stop(dev, 1); | |
| 142 | + ipoib_ib_dev_stop(dev); | |
| 143 | 143 | |
| 144 | 144 | err_disable: |
| 145 | 145 | clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); |
| @@ -157,8 +157,8 @@ static int ipoib_stop(struct net_device *dev) · 11 unmodified lines | ||
| 157 | 157 | |
| 158 | 158 | netif_stop_queue(dev); |
| 159 | 159 | |
| 160 | − ipoib_ib_dev_down(dev, 1); | |
| 161 | − ipoib_ib_dev_stop(dev, 0); | |
| 160 | + ipoib_ib_dev_down(dev); | |
| 161 | + ipoib_ib_dev_stop(dev); | |
| 162 | 162 | |
| 163 | 163 | if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { |
| 164 | 164 | struct ipoib_dev_priv *cpriv; |
| @@ -640,8 +640,10 @@ static void neigh_add_path(struct sk_buff *skb, u8 *daddr, · 475 unmodified lines | ||
| 640 | 640 | |
| 641 | 641 | if (!path->query && path_rec_start(dev, path)) |
| 642 | 642 | goto err_path; |
| 643 | − | |
| 644 | − __skb_queue_tail(&neigh->queue, skb); | |
| 643 | + if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) | |
| 644 | + __skb_queue_tail(&neigh->queue, skb); | |
| 645 | + else | |
| 646 | + goto err_drop; | |
| 645 | 647 | } |
| 646 | 648 | |
| 647 | 649 | spin_unlock_irqrestore(&priv->lock, flags); |
| @@ -676,7 +678,12 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, · 28 unmodified lines | ||
| 676 | 678 | new_path = 1; |
| 677 | 679 | } |
| 678 | 680 | if (path) { |
| 679 | − __skb_queue_tail(&path->queue, skb); | |
| 681 | + if (skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) { | |
| 682 | + __skb_queue_tail(&path->queue, skb); | |
| 683 | + } else { | |
| 684 | + ++dev->stats.tx_dropped; | |
| 685 | + dev_kfree_skb_any(skb); | |
| 686 | + } | |
| 680 | 687 | |
| 681 | 688 | if (!path->query && path_rec_start(dev, path)) { |
| 682 | 689 | spin_unlock_irqrestore(&priv->lock, flags); |
| @@ -839,7 +846,7 @@ static void ipoib_set_mcast_list(struct net_device *dev) · 156 unmodified lines | ||
| 839 | 846 | return; |
| 840 | 847 | } |
| 841 | 848 | |
| 842 | − queue_work(ipoib_workqueue, &priv->restart_task); | |
| 849 | + queue_work(priv->wq, &priv->restart_task); | |
| 843 | 850 | } |
| 844 | 851 | |
| 845 | 852 | static int ipoib_get_iflink(const struct net_device *dev) |
| @@ -966,7 +973,7 @@ static void ipoib_reap_neigh(struct work_struct *work) · 120 unmodified lines | ||
| 966 | 973 | __ipoib_reap_neigh(priv); |
| 967 | 974 | |
| 968 | 975 | if (!test_bit(IPOIB_STOP_NEIGH_GC, &priv->flags)) |
| 969 | − queue_delayed_work(ipoib_workqueue, &priv->neigh_reap_task, | |
| 976 | + queue_delayed_work(priv->wq, &priv->neigh_reap_task, | |
| 970 | 977 | arp_tbl.gc_interval); |
| 971 | 978 | } |
| 972 | 979 | |
| @@ -1145,7 +1152,7 @@ static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv) · 172 unmodified lines | ||
| 1145 | 1152 | |
| 1146 | 1153 | /* start garbage collection */ |
| 1147 | 1154 | clear_bit(IPOIB_STOP_NEIGH_GC, &priv->flags); |
| 1148 | − queue_delayed_work(ipoib_workqueue, &priv->neigh_reap_task, | |
| 1155 | + queue_delayed_work(priv->wq, &priv->neigh_reap_task, | |
| 1149 | 1156 | arp_tbl.gc_interval); |
| 1150 | 1157 | |
| 1151 | 1158 | return 0; |
| @@ -1274,15 +1281,13 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port) · 122 unmodified lines | ||
| 1274 | 1281 | { |
| 1275 | 1282 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
| 1276 | 1283 | |
| 1277 | − if (ipoib_neigh_hash_init(priv) < 0) | |
| 1278 | − goto out; | |
| 1279 | 1284 | /* Allocate RX/TX "rings" to hold queued skbs */ |
| 1280 | 1285 | priv->rx_ring = kzalloc(ipoib_recvq_size * sizeof *priv->rx_ring, |
| 1281 | 1286 | GFP_KERNEL); |
| 1282 | 1287 | if (!priv->rx_ring) { |
| 1283 | 1288 | printk(KERN_WARNING "%s: failed to allocate RX ring (%d entries)\n", |
| 1284 | 1289 | ca->name, ipoib_recvq_size); |
| 1285 | − goto out_neigh_hash_cleanup; | |
| 1290 | + goto out; | |
| 1286 | 1291 | } |
| 1287 | 1292 | |
| 1288 | 1293 | priv->tx_ring = vzalloc(ipoib_sendq_size * sizeof *priv->tx_ring); |
| @@ -1297,16 +1302,24 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port) · 8 unmodified lines | ||
| 1297 | 1302 | if (ipoib_ib_dev_init(dev, ca, port)) |
| 1298 | 1303 | goto out_tx_ring_cleanup; |
| 1299 | 1304 | |
| 1305 | + /* | |
| 1306 | + * Must be after ipoib_ib_dev_init so we can allocate a per | |
| 1307 | + * device wq there and use it here | |
| 1308 | + */ | |
| 1309 | + if (ipoib_neigh_hash_init(priv) < 0) | |
| 1310 | + goto out_dev_uninit; | |
| 1311 | + | |
| 1300 | 1312 | return 0; |
| 1301 | 1313 | |
| 1314 | +out_dev_uninit: | |
| 1315 | + ipoib_ib_dev_cleanup(dev); | |
| 1316 | + | |
| 1302 | 1317 | out_tx_ring_cleanup: |
| 1303 | 1318 | vfree(priv->tx_ring); |
| 1304 | 1319 | |
| 1305 | 1320 | out_rx_ring_cleanup: |
| 1306 | 1321 | kfree(priv->rx_ring); |
| 1307 | 1322 | |
| 1308 | −out_neigh_hash_cleanup: | |
| 1309 | − ipoib_neigh_hash_uninit(dev); | |
| 1310 | 1323 | out: |
| 1311 | 1324 | return -ENOMEM; |
| 1312 | 1325 | } |
| @@ -1329,6 +1342,12 @@ void ipoib_dev_cleanup(struct net_device *dev) · 16 unmodified lines | ||
| 1329 | 1342 | } |
| 1330 | 1343 | unregister_netdevice_many(&head); |
| 1331 | 1344 | |
| 1345 | + /* | |
| 1346 | + * Must be before ipoib_ib_dev_cleanup or we delete an in use | |
| 1347 | + * work queue | |
| 1348 | + */ | |
| 1349 | + ipoib_neigh_hash_uninit(dev); | |
| 1350 | + | |
| 1332 | 1351 | ipoib_ib_dev_cleanup(dev); |
| 1333 | 1352 | |
| 1334 | 1353 | kfree(priv->rx_ring); |
| @@ -1336,8 +1355,6 @@ void ipoib_dev_cleanup(struct net_device *dev) · 1 unmodified line | ||
| 1336 | 1355 | |
| 1337 | 1356 | priv->rx_ring = NULL; |
| 1338 | 1357 | priv->tx_ring = NULL; |
| 1339 | − | |
| 1340 | − ipoib_neigh_hash_uninit(dev); | |
| 1341 | 1358 | } |
| 1342 | 1359 | |
| 1343 | 1360 | static const struct header_ops ipoib_header_ops = { |
| @@ -1646,10 +1663,11 @@ sysfs_failed: · 302 unmodified lines | ||
| 1646 | 1663 | |
| 1647 | 1664 | register_failed: |
| 1648 | 1665 | ib_unregister_event_handler(&priv->event_handler); |
| 1666 | + flush_workqueue(ipoib_workqueue); | |
| 1649 | 1667 | /* Stop GC if started before flush */ |
| 1650 | 1668 | set_bit(IPOIB_STOP_NEIGH_GC, &priv->flags); |
| 1651 | 1669 | cancel_delayed_work(&priv->neigh_reap_task); |
| 1652 | − flush_workqueue(ipoib_workqueue); | |
| 1670 | + flush_workqueue(priv->wq); | |
| 1653 | 1671 | |
| 1654 | 1672 | event_failed: |
| 1655 | 1673 | ipoib_dev_cleanup(priv->dev); |
| @@ -1712,6 +1730,7 @@ static void ipoib_remove_one(struct ib_device *device) · 56 unmodified lines | ||
| 1712 | 1730 | |
| 1713 | 1731 | list_for_each_entry_safe(priv, tmp, dev_list, list) { |
| 1714 | 1732 | ib_unregister_event_handler(&priv->event_handler); |
| 1733 | + flush_workqueue(ipoib_workqueue); | |
| 1715 | 1734 | |
| 1716 | 1735 | rtnl_lock(); |
| 1717 | 1736 | dev_change_flags(priv->dev, priv->dev->flags & ~IFF_UP); |
| @@ -1720,7 +1739,7 @@ static void ipoib_remove_one(struct ib_device *device) · 2 unmodified lines | ||
| 1720 | 1739 | /* Stop GC */ |
| 1721 | 1740 | set_bit(IPOIB_STOP_NEIGH_GC, &priv->flags); |
| 1722 | 1741 | cancel_delayed_work(&priv->neigh_reap_task); |
| 1723 | − flush_workqueue(ipoib_workqueue); | |
| 1742 | + flush_workqueue(priv->wq); | |
| 1724 | 1743 | |
| 1725 | 1744 | unregister_netdev(priv->dev); |
| 1726 | 1745 | free_netdev(priv->dev); |
| @@ -1755,14 +1774,16 @@ static int __init ipoib_init_module(void) · 28 unmodified lines | ||
| 1755 | 1774 | return ret; |
| 1756 | 1775 | |
| 1757 | 1776 | /* |
| 1758 | − * We create our own workqueue mainly because we want to be | |
| 1759 | − * able to flush it when devices are being removed. We can't | |
| 1760 | − * use schedule_work()/flush_scheduled_work() because both | |
| 1761 | − * unregister_netdev() and linkwatch_event take the rtnl lock, | |
| 1762 | − * so flush_scheduled_work() can deadlock during device | |
| 1763 | − * removal. | |
| 1777 | + * We create a global workqueue here that is used for all flush | |
| 1778 | + * operations. However, if you attempt to flush a workqueue | |
| 1779 | + * from a task on that same workqueue, it deadlocks the system. | |
| 1780 | + * We want to be able to flush the tasks associated with a | |
| 1781 | + * specific net device, so we also create a workqueue for each | |
| 1782 | + * netdevice. We queue up the tasks for that device only on | |
| 1783 | + * its private workqueue, and we only queue up flush events | |
| 1784 | + * on our global flush workqueue. This avoids the deadlocks. | |
| 1764 | 1785 | */ |
| 1765 | − ipoib_workqueue = create_singlethread_workqueue("ipoib"); | |
| 1786 | + ipoib_workqueue = create_singlethread_workqueue("ipoib_flush"); | |
| 1766 | 1787 | if (!ipoib_workqueue) { |
| 1767 | 1788 | ret = -ENOMEM; |
| 1768 | 1789 | goto err_fs; |
| @@ -55,8 +55,6 @@ MODULE_PARM_DESC(mcast_debug_level, · 54 unmodified lines | ||
| 55 | 55 | "Enable multicast debug tracing if > 0"); |
| 56 | 56 | #endif |
| 57 | 57 | |
| 58 | −static DEFINE_MUTEX(mcast_mutex); | |
| 59 | − | |
| 60 | 58 | struct ipoib_mcast_iter { |
| 61 | 59 | struct net_device *dev; |
| 62 | 60 | union ib_gid mgid; |
| @@ -66,6 +64,48 @@ struct ipoib_mcast_iter { · 3 unmodified lines | ||
| 66 | 64 | unsigned int send_only; |
| 67 | 65 | }; |
| 68 | 66 | |
| 67 | +/* | |
| 68 | + * This should be called with the priv->lock held | |
| 69 | + */ | |
| 70 | +static void __ipoib_mcast_schedule_join_thread(struct ipoib_dev_priv *priv, | |
| 71 | + struct ipoib_mcast *mcast, | |
| 72 | + bool delay) | |
| 73 | +{ | |
| 74 | + if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) | |
| 75 | + return; | |
| 76 | + | |
| 77 | + /* | |
| 78 | + * We will be scheduling *something*, so cancel whatever is | |
| 79 | + * currently scheduled first | |
| 80 | + */ | |
| 81 | + cancel_delayed_work(&priv->mcast_task); | |
| 82 | + if (mcast && delay) { | |
| 83 | + /* | |
| 84 | + * We had a failure and want to schedule a retry later | |
| 85 | + */ | |
| 86 | + mcast->backoff *= 2; | |
| 87 | + if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS) | |
| 88 | + mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS; | |
| 89 | + mcast->delay_until = jiffies + (mcast->backoff * HZ); | |
| 90 | + /* | |
| 91 | + * Mark this mcast for its delay, but restart the | |
| 92 | + * task immediately. The join task will make sure to | |
| 93 | + * clear out all entries without delays, and then | |
| 94 | + * schedule itself to run again when the earliest | |
| 95 | + * delay expires | |
| 96 | + */ | |
| 97 | + queue_delayed_work(priv->wq, &priv->mcast_task, 0); | |
| 98 | + } else if (delay) { | |
| 99 | + /* | |
| 100 | + * Special case of retrying after a failure to | |
| 101 | + * allocate the broadcast multicast group, wait | |
| 102 | + * 1 second and try again | |
| 103 | + */ | |
| 104 | + queue_delayed_work(priv->wq, &priv->mcast_task, HZ); | |
| 105 | + } else | |
| 106 | + queue_delayed_work(priv->wq, &priv->mcast_task, 0); | |
| 107 | +} | |
| 108 | + | |
| 69 | 109 | static void ipoib_mcast_free(struct ipoib_mcast *mcast) |
| 70 | 110 | { |
| 71 | 111 | struct net_device *dev = mcast->dev; |
| @@ -103,6 +143,7 @@ static struct ipoib_mcast *ipoib_mcast_alloc(struct net_device *dev, · 31 unmodified lines | ||
| 103 | 143 | |
| 104 | 144 | mcast->dev = dev; |
| 105 | 145 | mcast->created = jiffies; |
| 146 | + mcast->delay_until = jiffies; | |
| 106 | 147 | mcast->backoff = 1; |
| 107 | 148 | |
| 108 | 149 | INIT_LIST_HEAD(&mcast->list); |
| @@ -185,17 +226,27 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, · 76 unmodified lines | ||
| 185 | 226 | spin_unlock_irq(&priv->lock); |
| 186 | 227 | return -EAGAIN; |
| 187 | 228 | } |
| 188 | − priv->mcast_mtu = IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu)); | |
| 229 | + /*update priv member according to the new mcast*/ | |
| 230 | + priv->broadcast->mcmember.qkey = mcmember->qkey; | |
| 231 | + priv->broadcast->mcmember.mtu = mcmember->mtu; | |
| 232 | + priv->broadcast->mcmember.traffic_class = mcmember->traffic_class; | |
| 233 | + priv->broadcast->mcmember.rate = mcmember->rate; | |
| 234 | + priv->broadcast->mcmember.sl = mcmember->sl; | |
| 235 | + priv->broadcast->mcmember.flow_label = mcmember->flow_label; | |
| 236 | + priv->broadcast->mcmember.hop_limit = mcmember->hop_limit; | |
| 237 | + /* assume if the admin and the mcast are the same both can be changed */ | |
| 238 | + if (priv->mcast_mtu == priv->admin_mtu) | |
| 239 | + priv->admin_mtu = | |
| 240 | + priv->mcast_mtu = | |
| 241 | + IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu)); | |
| 242 | + else | |
| 243 | + priv->mcast_mtu = | |
| 244 | + IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu)); | |
| 245 | + | |
| 189 | 246 | priv->qkey = be32_to_cpu(priv->broadcast->mcmember.qkey); |
| 190 | 247 | spin_unlock_irq(&priv->lock); |
| 191 | 248 | priv->tx_wr.wr.ud.remote_qkey = priv->qkey; |
| 192 | 249 | set_qkey = 1; |
| 193 | − | |
| 194 | − if (!ipoib_cm_admin_enabled(dev)) { | |
| 195 | − rtnl_lock(); | |
| 196 | − dev_set_mtu(dev, min(priv->mcast_mtu, priv->admin_mtu)); | |
| 197 | − rtnl_unlock(); | |
| 198 | − } | |
| 199 | 250 | } |
| 200 | 251 | |
| 201 | 252 | if (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) { |
| @@ -270,107 +321,35 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, · 68 unmodified lines | ||
| 270 | 321 | return 0; |
| 271 | 322 | } |
| 272 | 323 | |
| 273 | −static int | |
| 274 | −ipoib_mcast_sendonly_join_complete(int status, | |
| 275 | − struct ib_sa_multicast *multicast) | |
| 276 | −{ | |
| 277 | − struct ipoib_mcast *mcast = multicast->context; | |
| 278 | − struct net_device *dev = mcast->dev; | |
| 279 | − | |
| 280 | − /* We trap for port events ourselves. */ | |
| 281 | − if (status == -ENETRESET) | |
| 282 | − return 0; | |
| 283 | − | |
| 284 | − if (!status) | |
| 285 | − status = ipoib_mcast_join_finish(mcast, &multicast->rec); | |
| 286 | − | |
| 287 | − if (status) { | |
| 288 | − if (mcast->logcount++ < 20) | |
| 289 | − ipoib_dbg_mcast(netdev_priv(dev), "multicast join failed for %pI6, status %d\n", | |
| 290 | − mcast->mcmember.mgid.raw, status); | |
| 291 | − | |
| 292 | − /* Flush out any queued packets */ | |
| 293 | − netif_tx_lock_bh(dev); | |
| 294 | − while (!skb_queue_empty(&mcast->pkt_queue)) { | |
| 295 | − ++dev->stats.tx_dropped; | |
| 296 | − dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue)); | |
| 297 | − } | |
| 298 | − netif_tx_unlock_bh(dev); | |
| 299 | − | |
| 300 | − /* Clear the busy flag so we try again */ | |
| 301 | − status = test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, | |
| 302 | − &mcast->flags); | |
| 303 | − } | |
| 304 | − return status; | |
| 305 | −} | |
| 306 | − | |
| 307 | −static int ipoib_mcast_sendonly_join(struct ipoib_mcast *mcast) | |
| 308 | −{ | |
| 309 | − struct net_device *dev = mcast->dev; | |
| 310 | − struct ipoib_dev_priv *priv = netdev_priv(dev); | |
| 311 | − struct ib_sa_mcmember_rec rec = { | |
| 312 | −#if 0 /* Some SMs don't support send-only yet */ | |
| 313 | − .join_state = 4 | |
| 314 | −#else | |
| 315 | − .join_state = 1 | |
| 316 | −#endif | |
| 317 | − }; | |
| 318 | − int ret = 0; | |
| 319 | − | |
| 320 | − if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) { | |
| 321 | − ipoib_dbg_mcast(priv, "device shutting down, no multicast joins\n"); | |
| 322 | − return -ENODEV; | |
| 323 | − } | |
| 324 | − | |
| 325 | − if (test_and_set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags)) { | |
| 326 | − ipoib_dbg_mcast(priv, "multicast entry busy, skipping\n"); | |
| 327 | − return -EBUSY; | |
| 328 | − } | |
| 329 | − | |
| 330 | − rec.mgid = mcast->mcmember.mgid; | |
| 331 | − rec.port_gid = priv->local_gid; | |
| 332 | − rec.pkey = cpu_to_be16(priv->pkey); | |
| 333 | − | |
| 334 | − mcast->mc = ib_sa_join_multicast(&ipoib_sa_client, priv->ca, | |
| 335 | − priv->port, &rec, | |
| 336 | − IB_SA_MCMEMBER_REC_MGID | | |
| 337 | − IB_SA_MCMEMBER_REC_PORT_GID | | |
| 338 | − IB_SA_MCMEMBER_REC_PKEY | | |
| 339 | − IB_SA_MCMEMBER_REC_JOIN_STATE, | |
| 340 | − GFP_ATOMIC, | |
| 341 | − ipoib_mcast_sendonly_join_complete, | |
| 342 | − mcast); | |
| 343 | − if (IS_ERR(mcast->mc)) { | |
| 344 | − ret = PTR_ERR(mcast->mc); | |
| 345 | − clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags); | |
| 346 | − ipoib_warn(priv, "ib_sa_join_multicast failed (ret = %d)\n", | |
| 347 | − ret); | |
| 348 | − } else { | |
| 349 | − ipoib_dbg_mcast(priv, "no multicast record for %pI6, starting join\n", | |
| 350 | − mcast->mcmember.mgid.raw); | |
| 351 | − } | |
| 352 | − | |
| 353 | − return ret; | |
| 354 | −} | |
| 355 | − | |
| 356 | 324 | void ipoib_mcast_carrier_on_task(struct work_struct *work) |
| 357 | 325 | { |
| 358 | 326 | struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv, |
| 359 | 327 | carrier_on_task); |
| 360 | 328 | struct ib_port_attr attr; |
| 361 | 329 | |
| 362 | − /* | |
| 363 | − * Take rtnl_lock to avoid racing with ipoib_stop() and | |
| 364 | − * turning the carrier back on while a device is being | |
| 365 | − * removed. | |
| 366 | − */ | |
| 367 | 330 | if (ib_query_port(priv->ca, priv->port, &attr) || |
| 368 | 331 | attr.state != IB_PORT_ACTIVE) { |
| 369 | 332 | ipoib_dbg(priv, "Keeping carrier off until IB port is active\n"); |
| 370 | 333 | return; |
| 371 | 334 | } |
| 372 | 335 | |
| 373 | − rtnl_lock(); | |
| 336 | + /* | |
| 337 | + * Take rtnl_lock to avoid racing with ipoib_stop() and | |
| 338 | + * turning the carrier back on while a device is being | |
| 339 | + * removed. However, ipoib_stop() will attempt to flush | |
| 340 | + * the workqueue while holding the rtnl lock, so loop | |
| 341 | + * on trylock until either we get the lock or we see | |
| 342 | + * FLAG_OPER_UP go away as that signals that we are bailing | |
| 343 | + * and can safely ignore the carrier on work. | |
| 344 | + */ | |
| 345 | + while (!rtnl_trylock()) { | |
| 346 | + if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) | |
| 347 | + return; | |
| 348 | + else | |
| 349 | + msleep(20); | |
| 350 | + } | |
| 351 | + if (!ipoib_cm_admin_enabled(priv->dev)) | |
| 352 | + dev_set_mtu(priv->dev, min(priv->mcast_mtu, priv->admin_mtu)); | |
| 374 | 353 | netif_carrier_on(priv->dev); |
| 375 | 354 | rtnl_unlock(); |
| 376 | 355 | } |
| @@ -382,7 +361,9 @@ static int ipoib_mcast_join_complete(int status, · 5 unmodified lines | ||
| 382 | 361 | struct net_device *dev = mcast->dev; |
| 383 | 362 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
| 384 | 363 | |
| 385 | − ipoib_dbg_mcast(priv, "join completion for %pI6 (status %d)\n", | |
| 364 | + ipoib_dbg_mcast(priv, "%sjoin completion for %pI6 (status %d)\n", | |
| 365 | + test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags) ? | |
| 366 | + "sendonly " : "", | |
| 386 | 367 | mcast->mcmember.mgid.raw, status); |
| 387 | 368 | |
| 388 | 369 | /* We trap for port events ourselves. */ |
| @@ -396,49 +377,74 @@ static int ipoib_mcast_join_complete(int status, · 7 unmodified lines | ||
| 396 | 377 | |
| 397 | 378 | if (!status) { |
| 398 | 379 | mcast->backoff = 1; |
| 399 | − mutex_lock(&mcast_mutex); | |
| 400 | − if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) | |
| 401 | − queue_delayed_work(ipoib_workqueue, | |
| 402 | − &priv->mcast_task, 0); | |
| 403 | − mutex_unlock(&mcast_mutex); | |
| 380 | + mcast->delay_until = jiffies; | |
| 404 | 381 | |
| 405 | 382 | /* |
| 406 | − * Defer carrier on work to ipoib_workqueue to avoid a | |
| 407 | − * deadlock on rtnl_lock here. | |
| 383 | + * Defer carrier on work to priv->wq to avoid a | |
| 384 | + * deadlock on rtnl_lock here. Requeue our multicast | |
| 385 | + * work too, which will end up happening right after | |
| 386 | + * our carrier on task work and will allow us to | |
| 387 | + * send out all of the non-broadcast joins | |
| 408 | 388 | */ |
| 409 | − if (mcast == priv->broadcast) | |
| 410 | − queue_work(ipoib_workqueue, &priv->carrier_on_task); | |
| 411 | − | |
| 412 | − status = 0; | |
| 413 | − goto out; | |
| 414 | − } | |
| 389 | + if (mcast == priv->broadcast) { | |
| 390 | + spin_lock_irq(&priv->lock); | |
| 391 | + queue_work(priv->wq, &priv->carrier_on_task); | |
| 392 | + __ipoib_mcast_schedule_join_thread(priv, NULL, 0); | |
| 393 | + goto out_locked; | |
| 394 | + } | |
| 395 | + } else { | |
| 396 | + if (mcast->logcount++ < 20) { | |
| 397 | + if (status == -ETIMEDOUT || status == -EAGAIN) { | |
| 398 | + ipoib_dbg_mcast(priv, "%smulticast join failed for %pI6, status %d\n", | |
| 399 | + test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags) ? "sendonly " : "", | |
| 400 | + mcast->mcmember.mgid.raw, status); | |
| 401 | + } else { | |
| 402 | + ipoib_warn(priv, "%smulticast join failed for %pI6, status %d\n", | |
| 403 | + test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags) ? "sendonly " : "", | |
| 404 | + mcast->mcmember.mgid.raw, status); | |
| 405 | + } | |
| 406 | + } | |
| 415 | 407 | |
| 416 | − if (mcast->logcount++ < 20) { | |
| 417 | − if (status == -ETIMEDOUT || status == -EAGAIN) { | |
| 418 | − ipoib_dbg_mcast(priv, "multicast join failed for %pI6, status %d\n", | |
| 419 | − mcast->mcmember.mgid.raw, status); | |
| 408 | + if (test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags) && | |
| 409 | + mcast->backoff >= 2) { | |
| 410 | + /* | |
| 411 | + * We only retry sendonly joins once before we drop | |
| 412 | + * the packet and quit trying to deal with the | |
| 413 | + * group. However, we leave the group in the | |
| 414 | + * mcast list as an unjoined group. If we want to | |
| 415 | + * try joining again, we simply queue up a packet | |
| 416 | + * and restart the join thread. The empty queue | |
| 417 | + * is why the join thread ignores this group. | |
| 418 | + */ | |
| 419 | + mcast->backoff = 1; | |
| 420 | + netif_tx_lock_bh(dev); | |
| 421 | + while (!skb_queue_empty(&mcast->pkt_queue)) { | |
| 422 | + ++dev->stats.tx_dropped; | |
| 423 | + dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue)); | |
| 424 | + } | |
| 425 | + netif_tx_unlock_bh(dev); | |
| 420 | 426 | } else { |
| 421 | − ipoib_warn(priv, "multicast join failed for %pI6, status %d\n", | |
| 422 | − mcast->mcmember.mgid.raw, status); | |
| 427 | + spin_lock_irq(&priv->lock); | |
| 428 | + /* Requeue this join task with a backoff delay */ | |
| 429 | + __ipoib_mcast_schedule_join_thread(priv, mcast, 1); | |
| 430 | + goto out_locked; | |
| 423 | 431 | } |
| 424 | 432 | } |
| 425 | − | |
| 426 | − mcast->backoff *= 2; | |
| 427 | − if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS) | |
| 428 | − mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS; | |
| 429 | − | |
| 430 | − /* Clear the busy flag so we try again */ | |
| 431 | − status = test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags); | |
| 432 | − | |
| 433 | − mutex_lock(&mcast_mutex); | |
| 433 | +out: | |
| 434 | 434 | spin_lock_irq(&priv->lock); |
| 435 | − if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) | |
| 436 | − queue_delayed_work(ipoib_workqueue, &priv->mcast_task, | |
| 437 | − mcast->backoff * HZ); | |
| 435 | +out_locked: | |
| 436 | + /* | |
| 437 | + * Make sure to set mcast->mc before we clear the busy flag to avoid | |
| 438 | + * racing with code that checks for BUSY before checking mcast->mc | |
| 439 | + */ | |
| 440 | + if (status) | |
| 441 | + mcast->mc = NULL; | |
| 442 | + else | |
| 443 | + mcast->mc = multicast; | |
| 444 | + clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags); | |
| 438 | 445 | spin_unlock_irq(&priv->lock); |
| 439 | − mutex_unlock(&mcast_mutex); | |
| 440 | −out: | |
| 441 | 446 | complete(&mcast->done); |
| 447 | + | |
| 442 | 448 | return status; |
| 443 | 449 | } |
| 444 | 450 | |
| @@ -446,6 +452,7 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast, · 1 unmodified line | ||
| 446 | 452 | int create) |
| 447 | 453 | { |
| 448 | 454 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
| 455 | + struct ib_sa_multicast *multicast; | |
| 449 | 456 | struct ib_sa_mcmember_rec rec = { |
| 450 | 457 | .join_state = 1 |
| 451 | 458 | }; |
| @@ -487,29 +494,18 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast, · 35 unmodified lines | ||
| 487 | 494 | rec.hop_limit = priv->broadcast->mcmember.hop_limit; |
| 488 | 495 | } |
| 489 | 496 | |
| 490 | − set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags); | |
| 491 | − init_completion(&mcast->done); | |
| 492 | − set_bit(IPOIB_MCAST_JOIN_STARTED, &mcast->flags); | |
| 493 | − | |
| 494 | − mcast->mc = ib_sa_join_multicast(&ipoib_sa_client, priv->ca, priv->port, | |
| 497 | + multicast = ib_sa_join_multicast(&ipoib_sa_client, priv->ca, priv->port, | |
| 495 | 498 | &rec, comp_mask, GFP_KERNEL, |
| 496 | 499 | ipoib_mcast_join_complete, mcast); |
| 497 | − if (IS_ERR(mcast->mc)) { | |
| 500 | + if (IS_ERR(multicast)) { | |
| 501 | + ret = PTR_ERR(multicast); | |
| 502 | + ipoib_warn(priv, "ib_sa_join_multicast failed, status %d\n", ret); | |
| 503 | + spin_lock_irq(&priv->lock); | |
| 504 | + /* Requeue this join task with a backoff delay */ | |
| 505 | + __ipoib_mcast_schedule_join_thread(priv, mcast, 1); | |
| 498 | 506 | clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags); |
| 507 | + spin_unlock_irq(&priv->lock); | |
| 499 | 508 | complete(&mcast->done); |
| 500 | − ret = PTR_ERR(mcast->mc); | |
| 501 | − ipoib_warn(priv, "ib_sa_join_multicast failed, status %d\n", ret); | |
| 502 | − | |
| 503 | − mcast->backoff *= 2; | |
| 504 | − if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS) | |
| 505 | − mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS; | |
| 506 | − | |
| 507 | − mutex_lock(&mcast_mutex); | |
| 508 | − if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) | |
| 509 | − queue_delayed_work(ipoib_workqueue, | |
| 510 | − &priv->mcast_task, | |
| 511 | − mcast->backoff * HZ); | |
| 512 | − mutex_unlock(&mcast_mutex); | |
| 513 | 509 | } |
| 514 | 510 | } |
| 515 | 511 | |
| @@ -519,8 +515,11 @@ void ipoib_mcast_join_task(struct work_struct *work) · 3 unmodified lines | ||
| 519 | 515 | container_of(work, struct ipoib_dev_priv, mcast_task.work); |
| 520 | 516 | struct net_device *dev = priv->dev; |
| 521 | 517 | struct ib_port_attr port_attr; |
| 518 | + unsigned long delay_until = 0; | |
| 519 | + struct ipoib_mcast *mcast = NULL; | |
| 520 | + int create = 1; | |
| 522 | 521 | |
| 523 | − if (!test_bit(IPOIB_MCAST_RUN, &priv->flags)) | |
| 522 | + if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) | |
| 524 | 523 | return; |
| 525 | 524 | |
| 526 | 525 | if (ib_query_port(priv->ca, priv->port, &port_attr) || |
| @@ -536,93 +535,118 @@ void ipoib_mcast_join_task(struct work_struct *work) · 9 unmodified lines | ||
| 536 | 535 | else |
| 537 | 536 | memcpy(priv->dev->dev_addr + 4, priv->local_gid.raw, sizeof (union ib_gid)); |
| 538 | 537 | |
| 538 | + spin_lock_irq(&priv->lock); | |
| 539 | + if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) | |
| 540 | + goto out; | |
| 541 | + | |
| 539 | 542 | if (!priv->broadcast) { |
| 540 | 543 | struct ipoib_mcast *broadcast; |
| 541 | 544 | |
| 542 | − if (!test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) | |
| 543 | − return; | |
| 544 | − | |
| 545 | − broadcast = ipoib_mcast_alloc(dev, 1); | |
| 545 | + broadcast = ipoib_mcast_alloc(dev, 0); | |
| 546 | 546 | if (!broadcast) { |
| 547 | 547 | ipoib_warn(priv, "failed to allocate broadcast group\n"); |
| 548 | − mutex_lock(&mcast_mutex); | |
| 549 | − if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) | |
| 550 | − queue_delayed_work(ipoib_workqueue, | |
| 551 | − &priv->mcast_task, HZ); | |
| 552 | − mutex_unlock(&mcast_mutex); | |
| 553 | − return; | |
| 548 | + /* | |
| 549 | + * Restart us after a 1 second delay to retry | |
| 550 | + * creating our broadcast group and attaching to | |
| 551 | + * it. Until this succeeds, this ipoib dev is | |
| 552 | + * completely stalled (multicast wise). | |
| 553 | + */ | |
| 554 | + __ipoib_mcast_schedule_join_thread(priv, NULL, 1); | |
| 555 | + goto out; | |
| 554 | 556 | } |
| 555 | 557 | |
| 556 | − spin_lock_irq(&priv->lock); | |
| 557 | 558 | memcpy(broadcast->mcmember.mgid.raw, priv->dev->broadcast + 4, |
| 558 | 559 | sizeof (union ib_gid)); |
| 559 | 560 | priv->broadcast = broadcast; |
| 560 | 561 | |
| 561 | 562 | __ipoib_mcast_add(dev, priv->broadcast); |
| 562 | − spin_unlock_irq(&priv->lock); | |
| 563 | 563 | } |
| 564 | 564 | |
| 565 | 565 | if (!test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags)) { |
| 566 | − if (!test_bit(IPOIB_MCAST_FLAG_BUSY, &priv->broadcast->flags)) | |
| 567 | − ipoib_mcast_join(dev, priv->broadcast, 0); | |
| 568 | − return; | |
| 569 | − } | |
| 570 | − | |
| 571 | − while (1) { | |
| 572 | − struct ipoib_mcast *mcast = NULL; | |
| 573 | − | |
| 574 | − spin_lock_irq(&priv->lock); | |
| 575 | − list_for_each_entry(mcast, &priv->multicast_list, list) { | |
| 576 | − if (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags) | |
| 577 | − && !test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags) | |
| 578 | − && !test_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags)) { | |
| 579 | − /* Found the next unjoined group */ | |
| 580 | − break; | |
| 566 | + if (IS_ERR_OR_NULL(priv->broadcast->mc) && | |
| 567 | + !test_bit(IPOIB_MCAST_FLAG_BUSY, &priv->broadcast->flags)) { | |
| 568 | + mcast = priv->broadcast; | |
| 569 | + create = 0; | |
| 570 | + if (mcast->backoff > 1 && | |
| 571 | + time_before(jiffies, mcast->delay_until)) { | |
| 572 | + delay_until = mcast->delay_until; | |
| 573 | + mcast = NULL; | |
| 581 | 574 | } |
| 582 | 575 | } |
| 583 | − spin_unlock_irq(&priv->lock); | |
| 576 | + goto out; | |
| 577 | + } | |
| 584 | 578 | |
| 585 | − if (&mcast->list == &priv->multicast_list) { | |
| 586 | − /* All done */ | |
| 587 | − break; | |
| 579 | + /* | |
| 580 | + * We'll never get here until the broadcast group is both allocated | |
| 581 | + * and attached | |
| 582 | + */ | |
| 583 | + list_for_each_entry(mcast, &priv->multicast_list, list) { | |
| 584 | + if (IS_ERR_OR_NULL(mcast->mc) && | |
| 585 | + !test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags) && | |
| 586 | + (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags) || | |
| 587 | + !skb_queue_empty(&mcast->pkt_queue))) { | |
| 588 | + if (mcast->backoff == 1 || | |
| 589 | + time_after_eq(jiffies, mcast->delay_until)) { | |
| 590 | + /* Found the next unjoined group */ | |
| 591 | + init_completion(&mcast->done); | |
| 592 | + set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags); | |
| 593 | + if (test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) | |
| 594 | + create = 0; | |
| 595 | + else | |
| 596 | + create = 1; | |
| 597 | + spin_unlock_irq(&priv->lock); | |
| 598 | + ipoib_mcast_join(dev, mcast, create); | |
| 599 | + spin_lock_irq(&priv->lock); | |
| 600 | + } else if (!delay_until || | |
| 601 | + time_before(mcast->delay_until, delay_until)) | |
| 602 | + delay_until = mcast->delay_until; | |
| 588 | 603 | } |
| 589 | − | |
| 590 | − ipoib_mcast_join(dev, mcast, 1); | |
| 591 | − return; | |
| 592 | 604 | } |
| 593 | 605 | |
| 594 | − ipoib_dbg_mcast(priv, "successfully joined all multicast groups\n"); | |
| 606 | + mcast = NULL; | |
| 607 | + ipoib_dbg_mcast(priv, "successfully started all multicast joins\n"); | |
| 595 | 608 | |
| 596 | − clear_bit(IPOIB_MCAST_RUN, &priv->flags); | |
| 609 | +out: | |
| 610 | + if (delay_until) { | |
| 611 | + cancel_delayed_work(&priv->mcast_task); | |
| 612 | + queue_delayed_work(priv->wq, &priv->mcast_task, | |
| 613 | + delay_until - jiffies); | |
| 614 | + } | |
| 615 | + if (mcast) { | |
| 616 | + init_completion(&mcast->done); | |
| 617 | + set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags); | |
| 618 | + } | |
| 619 | + spin_unlock_irq(&priv->lock); | |
| 620 | + if (mcast) | |
| 621 | + ipoib_mcast_join(dev, mcast, create); | |
| 597 | 622 | } |
| 598 | 623 | |
| 599 | 624 | int ipoib_mcast_start_thread(struct net_device *dev) |
| 600 | 625 | { |
| 601 | 626 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
| 627 | + unsigned long flags; | |
| 602 | 628 | |
| 603 | 629 | ipoib_dbg_mcast(priv, "starting multicast thread\n"); |
| 604 | 630 | |
| 605 | − mutex_lock(&mcast_mutex); | |
| 606 | − if (!test_and_set_bit(IPOIB_MCAST_RUN, &priv->flags)) | |
| 607 | − queue_delayed_work(ipoib_workqueue, &priv->mcast_task, 0); | |
| 608 | − mutex_unlock(&mcast_mutex); | |
| 631 | + spin_lock_irqsave(&priv->lock, flags); | |
| 632 | + __ipoib_mcast_schedule_join_thread(priv, NULL, 0); | |
| 633 | + spin_unlock_irqrestore(&priv->lock, flags); | |
| 609 | 634 | |
| 610 | 635 | return 0; |
| 611 | 636 | } |
| 612 | 637 | |
| 613 | −int ipoib_mcast_stop_thread(struct net_device *dev, int flush) | |
| 638 | +int ipoib_mcast_stop_thread(struct net_device *dev) | |
| 614 | 639 | { |
| 615 | 640 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
| 641 | + unsigned long flags; | |
| 616 | 642 | |
| 617 | 643 | ipoib_dbg_mcast(priv, "stopping multicast thread\n"); |
| 618 | 644 | |
| 619 | − mutex_lock(&mcast_mutex); | |
| 620 | − clear_bit(IPOIB_MCAST_RUN, &priv->flags); | |
| 645 | + spin_lock_irqsave(&priv->lock, flags); | |
| 621 | 646 | cancel_delayed_work(&priv->mcast_task); |
| 622 | − mutex_unlock(&mcast_mutex); | |
| 647 | + spin_unlock_irqrestore(&priv->lock, flags); | |
| 623 | 648 | |
| 624 | − if (flush) | |
| 625 | − flush_workqueue(ipoib_workqueue); | |
| 649 | + flush_workqueue(priv->wq); | |
| 626 | 650 | |
| 627 | 651 | return 0; |
| 628 | 652 | } |
| @@ -633,6 +657,9 @@ static int ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast *mcast) · 4 unmodified lines | ||
| 633 | 657 | int ret = 0; |
| 634 | 658 | |
| 635 | 659 | if (test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags)) |
| 660 | + ipoib_warn(priv, "ipoib_mcast_leave on an in-flight join\n"); | |
| 661 | + | |
| 662 | + if (!IS_ERR_OR_NULL(mcast->mc)) | |
| 636 | 663 | ib_sa_free_multicast(mcast->mc); |
| 637 | 664 | |
| 638 | 665 | if (test_and_clear_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags)) { |
| @@ -644,7 +671,9 @@ static int ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast *mcast) · 5 unmodified lines | ||
| 644 | 671 | be16_to_cpu(mcast->mcmember.mlid)); |
| 645 | 672 | if (ret) |
| 646 | 673 | ipoib_warn(priv, "ib_detach_mcast failed (result = %d)\n", ret); |
| 647 | − } | |
| 674 | + } else if (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) | |
| 675 | + ipoib_dbg(priv, "leaving with no mcmember but not a " | |
| 676 | + "SENDONLY join\n"); | |
| 648 | 677 | |
| 649 | 678 | return 0; |
| 650 | 679 | } |
| @@ -667,49 +696,37 @@ void ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb) · 16 unmodified lines | ||
| 667 | 696 | } |
| 668 | 697 | |
| 669 | 698 | mcast = __ipoib_mcast_find(dev, mgid); |
| 670 | − if (!mcast) { | |
| 671 | − /* Let's create a new send only group now */ | |
| 672 | − ipoib_dbg_mcast(priv, "setting up send only multicast group for %pI6\n", | |
| 673 | − mgid); | |
| 674 | − | |
| 675 | − mcast = ipoib_mcast_alloc(dev, 0); | |
| 699 | + if (!mcast || !mcast->ah) { | |
| 676 | 700 | if (!mcast) { |
| 677 | − ipoib_warn(priv, "unable to allocate memory for " | |
| 678 | − "multicast structure\n"); | |
| 679 | − ++dev->stats.tx_dropped; | |
| 680 | − dev_kfree_skb_any(skb); | |
| 681 | − goto out; | |
| 682 | − } | |
| 683 | − | |
| 684 | − set_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags); | |
| 685 | − memcpy(mcast->mcmember.mgid.raw, mgid, sizeof (union ib_gid)); | |
| 686 | − __ipoib_mcast_add(dev, mcast); | |
| 687 | − list_add_tail(&mcast->list, &priv->multicast_list); | |
| 688 | − } | |
| 701 | + /* Let's create a new send only group now */ | |
| 702 | + ipoib_dbg_mcast(priv, "setting up send only multicast group for %pI6\n", | |
| 703 | + mgid); | |
| 704 | + | |
| 705 | + mcast = ipoib_mcast_alloc(dev, 0); | |
| 706 | + if (!mcast) { | |
| 707 | + ipoib_warn(priv, "unable to allocate memory " | |
| 708 | + "for multicast structure\n"); | |
| 709 | + ++dev->stats.tx_dropped; | |
| 710 | + dev_kfree_skb_any(skb); | |
| 711 | + goto unlock; | |
| 712 | + } | |
| 689 | 713 | |
| 690 | − if (!mcast->ah) { | |
| 714 | + set_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags); | |
| 715 | + memcpy(mcast->mcmember.mgid.raw, mgid, | |
| 716 | + sizeof (union ib_gid)); | |
| 717 | + __ipoib_mcast_add(dev, mcast); | |
| 718 | + list_add_tail(&mcast->list, &priv->multicast_list); | |
| 719 | + } | |
| 691 | 720 | if (skb_queue_len(&mcast->pkt_queue) < IPOIB_MAX_MCAST_QUEUE) |
| 692 | 721 | skb_queue_tail(&mcast->pkt_queue, skb); |
| 693 | 722 | else { |
| 694 | 723 | ++dev->stats.tx_dropped; |
| 695 | 724 | dev_kfree_skb_any(skb); |
| 696 | 725 | } |
| 697 | − | |
| 698 | − if (test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags)) | |
| 699 | − ipoib_dbg_mcast(priv, "no address vector, " | |
| 700 | − "but multicast join already started\n"); | |
| 701 | − else if (test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) | |
| 702 | − ipoib_mcast_sendonly_join(mcast); | |
| 703 | − | |
| 704 | − /* | |
| 705 | − * If lookup completes between here and out:, don't | |
| 706 | − * want to send packet twice. | |
| 707 | − */ | |
| 708 | − mcast = NULL; | |
| 709 | − } | |
| 710 | − | |
| 711 | −out: | |
| 712 | − if (mcast && mcast->ah) { | |
| 726 | + if (!test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags)) { | |
| 727 | + __ipoib_mcast_schedule_join_thread(priv, NULL, 0); | |
| 728 | + } | |
| 729 | + } else { | |
| 713 | 730 | struct ipoib_neigh *neigh; |
| 714 | 731 | |
| 715 | 732 | spin_unlock_irqrestore(&priv->lock, flags); |
| @@ -759,9 +776,12 @@ void ipoib_mcast_dev_flush(struct net_device *dev) · 43 unmodified lines | ||
| 759 | 776 | |
| 760 | 777 | spin_unlock_irqrestore(&priv->lock, flags); |
| 761 | 778 | |
| 762 | − /* seperate between the wait to the leave*/ | |
| 779 | + /* | |
| 780 | + * make sure the in-flight joins have finished before we attempt | |
| 781 | + * to leave | |
| 782 | + */ | |
| 763 | 783 | list_for_each_entry_safe(mcast, tmcast, &remove_list, list) |
| 764 | − if (test_bit(IPOIB_MCAST_JOIN_STARTED, &mcast->flags)) | |
| 784 | + if (test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags)) | |
| 765 | 785 | wait_for_completion(&mcast->done); |
| 766 | 786 | |
| 767 | 787 | list_for_each_entry_safe(mcast, tmcast, &remove_list, list) { |
| @@ -792,9 +812,14 @@ void ipoib_mcast_restart_task(struct work_struct *work) · 24 unmodified lines | ||
| 792 | 812 | unsigned long flags; |
| 793 | 813 | struct ib_sa_mcmember_rec rec; |
| 794 | 814 | |
| 795 | − ipoib_dbg_mcast(priv, "restarting multicast task\n"); | |
| 815 | + if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) | |
| 816 | + /* | |
| 817 | + * shortcut...on shutdown flush is called next, just | |
| 818 | + * let it do all the work | |
| 819 | + */ | |
| 820 | + return; | |
| 796 | 821 | |
| 797 | − ipoib_mcast_stop_thread(dev, 0); | |
| 822 | + ipoib_dbg_mcast(priv, "restarting multicast task\n"); | |
| 798 | 823 | |
| 799 | 824 | local_irq_save(flags); |
| 800 | 825 | netif_addr_lock(dev); |
| @@ -880,14 +905,27 @@ void ipoib_mcast_restart_task(struct work_struct *work) · 79 unmodified lines | ||
| 880 | 905 | netif_addr_unlock(dev); |
| 881 | 906 | local_irq_restore(flags); |
| 882 | 907 | |
| 883 | − /* We have to cancel outside of the spinlock */ | |
| 908 | + /* | |
| 909 | + * make sure the in-flight joins have finished before we attempt | |
| 910 | + * to leave | |
| 911 | + */ | |
| 912 | + list_for_each_entry_safe(mcast, tmcast, &remove_list, list) | |
| 913 | + if (test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags)) | |
| 914 | + wait_for_completion(&mcast->done); | |
| 915 | + | |
| 884 | 916 | list_for_each_entry_safe(mcast, tmcast, &remove_list, list) { |
| 885 | 917 | ipoib_mcast_leave(mcast->dev, mcast); |
| 886 | 918 | ipoib_mcast_free(mcast); |
| 887 | 919 | } |
| 888 | 920 | |
| 889 | − if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) | |
| 890 | − ipoib_mcast_start_thread(dev); | |
| 921 | + /* | |
| 922 | + * Double check that we are still up | |
| 923 | + */ | |
| 924 | + if (test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) { | |
| 925 | + spin_lock_irqsave(&priv->lock, flags); | |
| 926 | + __ipoib_mcast_schedule_join_thread(priv, NULL, 0); | |
| 927 | + spin_unlock_irqrestore(&priv->lock, flags); | |
| 928 | + } | |
| 891 | 929 | } |
| 892 | 930 | |
| 893 | 931 | #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG |
| @@ -157,6 +157,16 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca) · 156 unmodified lines | ||
| 157 | 157 | goto out_free_pd; |
| 158 | 158 | } |
| 159 | 159 | |
| 160 | + /* | |
| 161 | + * the various IPoIB tasks assume they will never race against | |
| 162 | + * themselves, so always use a single thread workqueue | |
| 163 | + */ | |
| 164 | + priv->wq = create_singlethread_workqueue("ipoib_wq"); | |
| 165 | + if (!priv->wq) { | |
| 166 | + printk(KERN_WARNING "ipoib: failed to allocate device WQ\n"); | |
| 167 | + goto out_free_mr; | |
| 168 | + } | |
| 169 | + | |
| 160 | 170 | size = ipoib_recvq_size + 1; |
| 161 | 171 | ret = ipoib_cm_dev_init(dev); |
| 162 | 172 | if (!ret) { |
| @@ -165,12 +175,13 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca) · 2 unmodified lines | ||
| 165 | 175 | size += ipoib_recvq_size + 1; /* 1 extra for rx_drain_qp */ |
| 166 | 176 | else |
| 167 | 177 | size += ipoib_recvq_size * ipoib_max_conn_qp; |
| 168 | − } | |
| 178 | + } else | |
| 179 | + goto out_free_wq; | |
| 169 | 180 | |
| 170 | 181 | priv->recv_cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev, size, 0); |
| 171 | 182 | if (IS_ERR(priv->recv_cq)) { |
| 172 | 183 | printk(KERN_WARNING "%s: failed to create receive CQ\n", ca->name); |
| 173 | − goto out_free_mr; | |
| 184 | + goto out_cm_dev_cleanup; | |
| 174 | 185 | } |
| 175 | 186 | |
| 176 | 187 | priv->send_cq = ib_create_cq(priv->ca, ipoib_send_comp_handler, NULL, |
| @@ -216,15 +227,10 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca) · 39 unmodified lines | ||
| 216 | 227 | priv->tx_wr.send_flags = IB_SEND_SIGNALED; |
| 217 | 228 | |
| 218 | 229 | priv->rx_sge[0].lkey = priv->mr->lkey; |
| 219 | − if (ipoib_ud_need_sg(priv->max_ib_mtu)) { | |
| 220 | − priv->rx_sge[0].length = IPOIB_UD_HEAD_SIZE; | |
| 221 | − priv->rx_sge[1].length = PAGE_SIZE; | |
| 222 | − priv->rx_sge[1].lkey = priv->mr->lkey; | |
| 223 | − priv->rx_wr.num_sge = IPOIB_UD_RX_SG; | |
| 224 | − } else { | |
| 225 | − priv->rx_sge[0].length = IPOIB_UD_BUF_SIZE(priv->max_ib_mtu); | |
| 226 | − priv->rx_wr.num_sge = 1; | |
| 227 | − } | |
| 230 | + | |
| 231 | + priv->rx_sge[0].length = IPOIB_UD_BUF_SIZE(priv->max_ib_mtu); | |
| 232 | + priv->rx_wr.num_sge = 1; | |
| 233 | + | |
| 228 | 234 | priv->rx_wr.next = NULL; |
| 229 | 235 | priv->rx_wr.sg_list = priv->rx_sge; |
| 230 | 236 | |
| @@ -236,12 +242,19 @@ out_free_send_cq: · 5 unmodified lines | ||
| 236 | 242 | out_free_recv_cq: |
| 237 | 243 | ib_destroy_cq(priv->recv_cq); |
| 238 | 244 | |
| 245 | +out_cm_dev_cleanup: | |
| 246 | + ipoib_cm_dev_cleanup(dev); | |
| 247 | + | |
| 248 | +out_free_wq: | |
| 249 | + destroy_workqueue(priv->wq); | |
| 250 | + priv->wq = NULL; | |
| 251 | + | |
| 239 | 252 | out_free_mr: |
| 240 | 253 | ib_dereg_mr(priv->mr); |
| 241 | − ipoib_cm_dev_cleanup(dev); | |
| 242 | 254 | |
| 243 | 255 | out_free_pd: |
| 244 | 256 | ib_dealloc_pd(priv->pd); |
| 257 | + | |
| 245 | 258 | return -ENODEV; |
| 246 | 259 | } |
| 247 | 260 | |
| @@ -265,11 +278,18 @@ void ipoib_transport_dev_cleanup(struct net_device *dev) · 17 unmodified lines | ||
| 265 | 278 | |
| 266 | 279 | ipoib_cm_dev_cleanup(dev); |
| 267 | 280 | |
| 281 | + if (priv->wq) { | |
| 282 | + flush_workqueue(priv->wq); | |
| 283 | + destroy_workqueue(priv->wq); | |
| 284 | + priv->wq = NULL; | |
| 285 | + } | |
| 286 | + | |
| 268 | 287 | if (ib_dereg_mr(priv->mr)) |
| 269 | 288 | ipoib_warn(priv, "ib_dereg_mr failed\n"); |
| 270 | 289 | |
| 271 | 290 | if (ib_dealloc_pd(priv->pd)) |
| 272 | 291 | ipoib_warn(priv, "ib_dealloc_pd failed\n"); |
| 292 | + | |
| 273 | 293 | } |
| 274 | 294 | |
| 275 | 295 | void ipoib_event(struct ib_event_handler *handler, |
| @@ -69,7 +69,7 @@ · 68 unmodified lines | ||
| 69 | 69 | |
| 70 | 70 | #define DRV_NAME "iser" |
| 71 | 71 | #define PFX DRV_NAME ": " |
| 72 | −#define DRV_VER "1.5" | |
| 72 | +#define DRV_VER "1.6" | |
| 73 | 73 | |
| 74 | 74 | #define iser_dbg(fmt, arg...) \ |
| 75 | 75 | do { \ |
| @@ -218,22 +218,21 @@ enum iser_data_dir { · 142 unmodified lines | ||
| 218 | 218 | /** |
| 219 | 219 | * struct iser_data_buf - iSER data buffer |
| 220 | 220 | * |
| 221 | − * @buf: pointer to the sg list | |
| 221 | + * @sg: pointer to the sg list | |
| 222 | 222 | * @size: num entries of this sg |
| 223 | 223 | * @data_len: total beffer byte len |
| 224 | 224 | * @dma_nents: returned by dma_map_sg |
| 225 | − * @copy_buf: allocated copy buf for SGs unaligned | |
| 226 | − * for rdma which are copied | |
| 227 | − * @sg_single: SG-ified clone of a non SG SC or | |
| 228 | − * unaligned SG | |
| 225 | + * @orig_sg: pointer to the original sg list (in case | |
| 226 | + * we used a copy) | |
| 227 | + * @orig_size: num entris of orig sg list | |
| 229 | 228 | */ |
| 230 | 229 | struct iser_data_buf { |
| 231 | − void *buf; | |
| 230 | + struct scatterlist *sg; | |
| 232 | 231 | unsigned int size; |
| 233 | 232 | unsigned long data_len; |
| 234 | 233 | unsigned int dma_nents; |
| 235 | − char *copy_buf; | |
| 236 | − struct scatterlist sg_single; | |
| 234 | + struct scatterlist *orig_sg; | |
| 235 | + unsigned int orig_size; | |
| 237 | 236 | }; |
| 238 | 237 | |
| 239 | 238 | /* fwd declarations */ |
| @@ -244,35 +243,14 @@ struct iscsi_endpoint; · 4 unmodified lines | ||
| 244 | 243 | /** |
| 245 | 244 | * struct iser_mem_reg - iSER memory registration info |
| 246 | 245 | * |
| 247 | − * @lkey: MR local key | |
| 248 | − * @rkey: MR remote key | |
| 249 | − * @va: MR start address (buffer va) | |
| 250 | − * @len: MR length | |
| 246 | + * @sge: memory region sg element | |
| 247 | + * @rkey: memory region remote key | |
| 251 | 248 | * @mem_h: pointer to registration context (FMR/Fastreg) |
| 252 | 249 | */ |
| 253 | 250 | struct iser_mem_reg { |
| 254 | − u32 lkey; | |
| 255 | − u32 rkey; | |
| 256 | − u64 va; | |
| 257 | − u64 len; | |
| 258 | − void *mem_h; | |
| 259 | −}; | |
| 260 | − | |
| 261 | −/** | |
| 262 | − * struct iser_regd_buf - iSER buffer registration desc | |
| 263 | − * | |
| 264 | − * @reg: memory registration info | |
| 265 | − * @virt_addr: virtual address of buffer | |
| 266 | − * @device: reference to iser device | |
| 267 | − * @direction: dma direction (for dma_unmap) | |
| 268 | − * @data_size: data buffer size in bytes | |
| 269 | − */ | |
| 270 | −struct iser_regd_buf { | |
| 271 | − struct iser_mem_reg reg; | |
| 272 | − void *virt_addr; | |
| 273 | − struct iser_device *device; | |
| 274 | − enum dma_data_direction direction; | |
| 275 | − unsigned int data_size; | |
| 251 | + struct ib_sge sge; | |
| 252 | + u32 rkey; | |
| 253 | + void *mem_h; | |
| 276 | 254 | }; |
| 277 | 255 | |
| 278 | 256 | enum iser_desc_type { |
| @@ -534,11 +512,9 @@ struct iser_conn { · 255 unmodified lines | ||
| 534 | 512 | * @sc: link to scsi command |
| 535 | 513 | * @command_sent: indicate if command was sent |
| 536 | 514 | * @dir: iser data direction |
| 537 | − * @rdma_regd: task rdma registration desc | |
| 515 | + * @rdma_reg: task rdma registration desc | |
| 538 | 516 | * @data: iser data buffer desc |
| 539 | − * @data_copy: iser data copy buffer desc (bounce buffer) | |
| 540 | 517 | * @prot: iser protection buffer desc |
| 541 | − * @prot_copy: iser protection copy buffer desc (bounce buffer) | |
| 542 | 518 | */ |
| 543 | 519 | struct iscsi_iser_task { |
| 544 | 520 | struct iser_tx_desc desc; |
| @@ -547,11 +523,9 @@ struct iscsi_iser_task { · 2 unmodified lines | ||
| 547 | 523 | struct scsi_cmnd *sc; |
| 548 | 524 | int command_sent; |
| 549 | 525 | int dir[ISER_DIRS_NUM]; |
| 550 | − struct iser_regd_buf rdma_regd[ISER_DIRS_NUM]; | |
| 526 | + struct iser_mem_reg rdma_reg[ISER_DIRS_NUM]; | |
| 551 | 527 | struct iser_data_buf data[ISER_DIRS_NUM]; |
| 552 | − struct iser_data_buf data_copy[ISER_DIRS_NUM]; | |
| 553 | 528 | struct iser_data_buf prot[ISER_DIRS_NUM]; |
| 554 | − struct iser_data_buf prot_copy[ISER_DIRS_NUM]; | |
| 555 | 529 | }; |
| 556 | 530 | |
| 557 | 531 | struct iser_page_vec { |
| @@ -621,7 +595,6 @@ void iser_free_rx_descriptors(struct iser_conn *iser_conn); · 63 unmodified lines | ||
| 621 | 595 | |
| 622 | 596 | void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_task *iser_task, |
| 623 | 597 | struct iser_data_buf *mem, |
| 624 | − struct iser_data_buf *mem_copy, | |
| 625 | 598 | enum iser_data_dir cmd_dir); |
| 626 | 599 | |
| 627 | 600 | int iser_reg_rdma_mem_fmr(struct iscsi_iser_task *task, |
| @@ -634,10 +607,6 @@ int iser_connect(struct iser_conn *iser_conn, · 6 unmodified lines | ||
| 634 | 607 | struct sockaddr *dst_addr, |
| 635 | 608 | int non_blocking); |
| 636 | 609 | |
| 637 | −int iser_reg_page_vec(struct ib_conn *ib_conn, | |
| 638 | − struct iser_page_vec *page_vec, | |
| 639 | − struct iser_mem_reg *mem_reg); | |
| 640 | − | |
| 641 | 610 | void iser_unreg_mem_fmr(struct iscsi_iser_task *iser_task, |
| 642 | 611 | enum iser_data_dir cmd_dir); |
| 643 | 612 | void iser_unreg_mem_fastreg(struct iscsi_iser_task *iser_task, |
| @@ -667,4 +636,9 @@ int iser_create_fastreg_pool(struct ib_conn *ib_conn, unsigned cmds_max); · 23 unmodified lines | ||
| 667 | 636 | void iser_free_fastreg_pool(struct ib_conn *ib_conn); |
| 668 | 637 | u8 iser_check_task_pi_status(struct iscsi_iser_task *iser_task, |
| 669 | 638 | enum iser_data_dir cmd_dir, sector_t *sector); |
| 639 | +struct fast_reg_descriptor * | |
| 640 | +iser_reg_desc_get(struct ib_conn *ib_conn); | |
| 641 | +void | |
| 642 | +iser_reg_desc_put(struct ib_conn *ib_conn, | |
| 643 | + struct fast_reg_descriptor *desc); | |
| 670 | 644 | #endif |
| @@ -50,7 +50,7 @@ static int iser_prepare_read_cmd(struct iscsi_task *task) · 49 unmodified lines | ||
| 50 | 50 | { |
| 51 | 51 | struct iscsi_iser_task *iser_task = task->dd_data; |
| 52 | 52 | struct iser_device *device = iser_task->iser_conn->ib_conn.device; |
| 53 | − struct iser_regd_buf *regd_buf; | |
| 53 | + struct iser_mem_reg *mem_reg; | |
| 54 | 54 | int err; |
| 55 | 55 | struct iser_hdr *hdr = &iser_task->desc.iser_header; |
| 56 | 56 | struct iser_data_buf *buf_in = &iser_task->data[ISER_DIR_IN]; |
| @@ -78,15 +78,15 @@ static int iser_prepare_read_cmd(struct iscsi_task *task) · 21 unmodified lines | ||
| 78 | 78 | iser_err("Failed to set up Data-IN RDMA\n"); |
| 79 | 79 | return err; |
| 80 | 80 | } |
| 81 | − regd_buf = &iser_task->rdma_regd[ISER_DIR_IN]; | |
| 81 | + mem_reg = &iser_task->rdma_reg[ISER_DIR_IN]; | |
| 82 | 82 | |
| 83 | 83 | hdr->flags |= ISER_RSV; |
| 84 | − hdr->read_stag = cpu_to_be32(regd_buf->reg.rkey); | |
| 85 | − hdr->read_va = cpu_to_be64(regd_buf->reg.va); | |
| 84 | + hdr->read_stag = cpu_to_be32(mem_reg->rkey); | |
| 85 | + hdr->read_va = cpu_to_be64(mem_reg->sge.addr); | |
| 86 | 86 | |
| 87 | 87 | iser_dbg("Cmd itt:%d READ tags RKEY:%#.4X VA:%#llX\n", |
| 88 | − task->itt, regd_buf->reg.rkey, | |
| 89 | − (unsigned long long)regd_buf->reg.va); | |
| 88 | + task->itt, mem_reg->rkey, | |
| 89 | + (unsigned long long)mem_reg->sge.addr); | |
| 90 | 90 | |
| 91 | 91 | return 0; |
| 92 | 92 | } |
| @@ -104,7 +104,7 @@ iser_prepare_write_cmd(struct iscsi_task *task, · 11 unmodified lines | ||
| 104 | 104 | { |
| 105 | 105 | struct iscsi_iser_task *iser_task = task->dd_data; |
| 106 | 106 | struct iser_device *device = iser_task->iser_conn->ib_conn.device; |
| 107 | − struct iser_regd_buf *regd_buf; | |
| 107 | + struct iser_mem_reg *mem_reg; | |
| 108 | 108 | int err; |
| 109 | 109 | struct iser_hdr *hdr = &iser_task->desc.iser_header; |
| 110 | 110 | struct iser_data_buf *buf_out = &iser_task->data[ISER_DIR_OUT]; |
| @@ -134,25 +134,25 @@ iser_prepare_write_cmd(struct iscsi_task *task, · 23 unmodified lines | ||
| 134 | 134 | return err; |
| 135 | 135 | } |
| 136 | 136 | |
| 137 | − regd_buf = &iser_task->rdma_regd[ISER_DIR_OUT]; | |
| 137 | + mem_reg = &iser_task->rdma_reg[ISER_DIR_OUT]; | |
| 138 | 138 | |
| 139 | 139 | if (unsol_sz < edtl) { |
| 140 | 140 | hdr->flags |= ISER_WSV; |
| 141 | − hdr->write_stag = cpu_to_be32(regd_buf->reg.rkey); | |
| 142 | − hdr->write_va = cpu_to_be64(regd_buf->reg.va + unsol_sz); | |
| 141 | + hdr->write_stag = cpu_to_be32(mem_reg->rkey); | |
| 142 | + hdr->write_va = cpu_to_be64(mem_reg->sge.addr + unsol_sz); | |
| 143 | 143 | |
| 144 | 144 | iser_dbg("Cmd itt:%d, WRITE tags, RKEY:%#.4X " |
| 145 | 145 | "VA:%#llX + unsol:%d\n", |
| 146 | − task->itt, regd_buf->reg.rkey, | |
| 147 | − (unsigned long long)regd_buf->reg.va, unsol_sz); | |
| 146 | + task->itt, mem_reg->rkey, | |
| 147 | + (unsigned long long)mem_reg->sge.addr, unsol_sz); | |
| 148 | 148 | } |
| 149 | 149 | |
| 150 | 150 | if (imm_sz > 0) { |
| 151 | 151 | iser_dbg("Cmd itt:%d, WRITE, adding imm.data sz: %d\n", |
| 152 | 152 | task->itt, imm_sz); |
| 153 | − tx_dsg->addr = regd_buf->reg.va; | |
| 153 | + tx_dsg->addr = mem_reg->sge.addr; | |
| 154 | 154 | tx_dsg->length = imm_sz; |
| 155 | − tx_dsg->lkey = regd_buf->reg.lkey; | |
| 155 | + tx_dsg->lkey = mem_reg->sge.lkey; | |
| 156 | 156 | iser_task->desc.num_sge = 2; |
| 157 | 157 | } |
| 158 | 158 | |
| @@ -401,16 +401,16 @@ int iser_send_command(struct iscsi_conn *conn, · 242 unmodified lines | ||
| 401 | 401 | } |
| 402 | 402 | |
| 403 | 403 | if (scsi_sg_count(sc)) { /* using a scatter list */ |
| 404 | − data_buf->buf = scsi_sglist(sc); | |
| 404 | + data_buf->sg = scsi_sglist(sc); | |
| 405 | 405 | data_buf->size = scsi_sg_count(sc); |
| 406 | 406 | } |
| 407 | 407 | data_buf->data_len = scsi_bufflen(sc); |
| 408 | 408 | |
| 409 | 409 | if (scsi_prot_sg_count(sc)) { |
| 410 | − prot_buf->buf = scsi_prot_sglist(sc); | |
| 410 | + prot_buf->sg = scsi_prot_sglist(sc); | |
| 411 | 411 | prot_buf->size = scsi_prot_sg_count(sc); |
| 412 | − prot_buf->data_len = data_buf->data_len >> | |
| 413 | − ilog2(sc->device->sector_size) * 8; | |
| 412 | + prot_buf->data_len = (data_buf->data_len >> | |
| 413 | + ilog2(sc->device->sector_size)) * 8; | |
| 414 | 414 | } |
| 415 | 415 | |
| 416 | 416 | if (hdr->flags & ISCSI_FLAG_CMD_READ) { |
| @@ -450,7 +450,7 @@ int iser_send_data_out(struct iscsi_conn *conn, · 33 unmodified lines | ||
| 450 | 450 | struct iser_conn *iser_conn = conn->dd_data; |
| 451 | 451 | struct iscsi_iser_task *iser_task = task->dd_data; |
| 452 | 452 | struct iser_tx_desc *tx_desc = NULL; |
| 453 | − struct iser_regd_buf *regd_buf; | |
| 453 | + struct iser_mem_reg *mem_reg; | |
| 454 | 454 | unsigned long buf_offset; |
| 455 | 455 | unsigned long data_seg_len; |
| 456 | 456 | uint32_t itt; |
| @@ -477,11 +477,11 @@ int iser_send_data_out(struct iscsi_conn *conn, · 20 unmodified lines | ||
| 477 | 477 | /* build the tx desc */ |
| 478 | 478 | iser_initialize_task_headers(task, tx_desc); |
| 479 | 479 | |
| 480 | − regd_buf = &iser_task->rdma_regd[ISER_DIR_OUT]; | |
| 480 | + mem_reg = &iser_task->rdma_reg[ISER_DIR_OUT]; | |
| 481 | 481 | tx_dsg = &tx_desc->tx_sg[1]; |
| 482 | − tx_dsg->addr = regd_buf->reg.va + buf_offset; | |
| 483 | − tx_dsg->length = data_seg_len; | |
| 484 | − tx_dsg->lkey = regd_buf->reg.lkey; | |
| 482 | + tx_dsg->addr = mem_reg->sge.addr + buf_offset; | |
| 483 | + tx_dsg->length = data_seg_len; | |
| 484 | + tx_dsg->lkey = mem_reg->sge.lkey; | |
| 485 | 485 | tx_desc->num_sge = 2; |
| 486 | 486 | |
| 487 | 487 | if (buf_offset + data_seg_len > iser_task->data[ISER_DIR_OUT].data_len) { |
| @@ -658,10 +658,10 @@ void iser_task_rdma_init(struct iscsi_iser_task *iser_task) · 170 unmodified lines | ||
| 658 | 658 | iser_task->prot[ISER_DIR_IN].data_len = 0; |
| 659 | 659 | iser_task->prot[ISER_DIR_OUT].data_len = 0; |
| 660 | 660 | |
| 661 | − memset(&iser_task->rdma_regd[ISER_DIR_IN], 0, | |
| 662 | − sizeof(struct iser_regd_buf)); | |
| 663 | − memset(&iser_task->rdma_regd[ISER_DIR_OUT], 0, | |
| 664 | − sizeof(struct iser_regd_buf)); | |
| 661 | + memset(&iser_task->rdma_reg[ISER_DIR_IN], 0, | |
| 662 | + sizeof(struct iser_mem_reg)); | |
| 663 | + memset(&iser_task->rdma_reg[ISER_DIR_OUT], 0, | |
| 664 | + sizeof(struct iser_mem_reg)); | |
| 665 | 665 | } |
| 666 | 666 | |
| 667 | 667 | void iser_task_rdma_finalize(struct iscsi_iser_task *iser_task) |
| @@ -674,35 +674,31 @@ void iser_task_rdma_finalize(struct iscsi_iser_task *iser_task) · 6 unmodified lines | ||
| 674 | 674 | /* if we were reading, copy back to unaligned sglist, |
| 675 | 675 | * anyway dma_unmap and free the copy |
| 676 | 676 | */ |
| 677 | − if (iser_task->data_copy[ISER_DIR_IN].copy_buf != NULL) { | |
| 677 | + if (iser_task->data[ISER_DIR_IN].orig_sg) { | |
| 678 | 678 | is_rdma_data_aligned = 0; |
| 679 | 679 | iser_finalize_rdma_unaligned_sg(iser_task, |
| 680 | 680 | &iser_task->data[ISER_DIR_IN], |
| 681 | − &iser_task->data_copy[ISER_DIR_IN], | |
| 682 | 681 | ISER_DIR_IN); |
| 683 | 682 | } |
| 684 | 683 | |
| 685 | − if (iser_task->data_copy[ISER_DIR_OUT].copy_buf != NULL) { | |
| 684 | + if (iser_task->data[ISER_DIR_OUT].orig_sg) { | |
| 686 | 685 | is_rdma_data_aligned = 0; |
| 687 | 686 | iser_finalize_rdma_unaligned_sg(iser_task, |
| 688 | 687 | &iser_task->data[ISER_DIR_OUT], |
| 689 | − &iser_task->data_copy[ISER_DIR_OUT], | |
| 690 | 688 | ISER_DIR_OUT); |
| 691 | 689 | } |
| 692 | 690 | |
| 693 | − if (iser_task->prot_copy[ISER_DIR_IN].copy_buf != NULL) { | |
| 691 | + if (iser_task->prot[ISER_DIR_IN].orig_sg) { | |
| 694 | 692 | is_rdma_prot_aligned = 0; |
| 695 | 693 | iser_finalize_rdma_unaligned_sg(iser_task, |
| 696 | 694 | &iser_task->prot[ISER_DIR_IN], |
| 697 | − &iser_task->prot_copy[ISER_DIR_IN], | |
| 698 | 695 | ISER_DIR_IN); |
| 699 | 696 | } |
| 700 | 697 | |
| 701 | − if (iser_task->prot_copy[ISER_DIR_OUT].copy_buf != NULL) { | |
| 698 | + if (iser_task->prot[ISER_DIR_OUT].orig_sg) { | |
| 702 | 699 | is_rdma_prot_aligned = 0; |
| 703 | 700 | iser_finalize_rdma_unaligned_sg(iser_task, |
| 704 | 701 | &iser_task->prot[ISER_DIR_OUT], |
| 705 | − &iser_task->prot_copy[ISER_DIR_OUT], | |
| 706 | 702 | ISER_DIR_OUT); |
| 707 | 703 | } |
| 708 | 704 | |
| @@ -39,68 +39,173 @@ · 38 unmodified lines | ||
| 39 | 39 | |
| 40 | 40 | #include "iscsi_iser.h" |
| 41 | 41 | |
| 42 | −#define ISER_KMALLOC_THRESHOLD 0x20000 /* 128K - kmalloc limit */ | |
| 42 | +static void | |
| 43 | +iser_free_bounce_sg(struct iser_data_buf *data) | |
| 44 | +{ | |
| 45 | + struct scatterlist *sg; | |
| 46 | + int count; | |
| 43 | 47 | |
| 44 | −/** | |
| 45 | − * iser_start_rdma_unaligned_sg | |
| 46 | − */ | |
| 47 | −static int iser_start_rdma_unaligned_sg(struct iscsi_iser_task *iser_task, | |
| 48 | − struct iser_data_buf *data, | |
| 49 | − struct iser_data_buf *data_copy, | |
| 50 | − enum iser_data_dir cmd_dir) | |
| 48 | + for_each_sg(data->sg, sg, data->size, count) | |
| 49 | + __free_page(sg_page(sg)); | |
| 50 | + | |
| 51 | + kfree(data->sg); | |
| 52 | + | |
| 53 | + data->sg = data->orig_sg; | |
| 54 | + data->size = data->orig_size; | |
| 55 | + data->orig_sg = NULL; | |
| 56 | + data->orig_size = 0; | |
| 57 | +} | |
| 58 | + | |
| 59 | +static int | |
| 60 | +iser_alloc_bounce_sg(struct iser_data_buf *data) | |
| 51 | 61 | { |
| 52 | − struct ib_device *dev = iser_task->iser_conn->ib_conn.device->ib_device; | |
| 53 | − struct scatterlist *sgl = (struct scatterlist *)data->buf; | |
| 54 | 62 | struct scatterlist *sg; |
| 55 | − char *mem = NULL; | |
| 56 | − unsigned long cmd_data_len = 0; | |
| 57 | − int dma_nents, i; | |
| 63 | + struct page *page; | |
| 64 | + unsigned long length = data->data_len; | |
| 65 | + int i = 0, nents = DIV_ROUND_UP(length, PAGE_SIZE); | |
| 58 | 66 | |
| 59 | − for_each_sg(sgl, sg, data->size, i) | |
| 60 | − cmd_data_len += ib_sg_dma_len(dev, sg); | |
| 67 | + sg = kcalloc(nents, sizeof(*sg), GFP_ATOMIC); | |
| 68 | + if (!sg) | |
| 69 | + goto err; | |
| 61 | 70 | |
| 62 | − if (cmd_data_len > ISER_KMALLOC_THRESHOLD) | |
| 63 | − mem = (void *)__get_free_pages(GFP_ATOMIC, | |
| 64 | − ilog2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT); | |
| 65 | − else | |
| 66 | − mem = kmalloc(cmd_data_len, GFP_ATOMIC); | |
| 71 | + sg_init_table(sg, nents); | |
| 72 | + while (length) { | |
| 73 | + u32 page_len = min_t(u32, length, PAGE_SIZE); | |
| 67 | 74 | |
| 68 | − if (mem == NULL) { | |
| 69 | − iser_err("Failed to allocate mem size %d %d for copying sglist\n", | |
| 70 | − data->size, (int)cmd_data_len); | |
| 71 | − return -ENOMEM; | |
| 75 | + page = alloc_page(GFP_ATOMIC); | |
| 76 | + if (!page) | |
| 77 | + goto err; | |
| 78 | + | |
| 79 | + sg_set_page(&sg[i], page, page_len, 0); | |
| 80 | + length -= page_len; | |
| 81 | + i++; | |
| 72 | 82 | } |
| 73 | 83 | |
| 74 | − if (cmd_dir == ISER_DIR_OUT) { | |
| 75 | − /* copy the unaligned sg the buffer which is used for RDMA */ | |
| 76 | − char *p, *from; | |
| 77 | − | |
| 78 | − sgl = (struct scatterlist *)data->buf; | |
| 79 | − p = mem; | |
| 80 | − for_each_sg(sgl, sg, data->size, i) { | |
| 81 | − from = kmap_atomic(sg_page(sg)); | |
| 82 | − memcpy(p, | |
| 83 | − from + sg->offset, | |
| 84 | − sg->length); | |
| 85 | − kunmap_atomic(from); | |
| 86 | − p += sg->length; | |
| 84 | + data->orig_sg = data->sg; | |
| 85 | + data->orig_size = data->size; | |
| 86 | + data->sg = sg; | |
| 87 | + data->size = nents; | |
| 88 | + | |
| 89 | + return 0; | |
| 90 | + | |
| 91 | +err: | |
| 92 | + for (; i > 0; i--) | |
| 93 | + __free_page(sg_page(&sg[i - 1])); | |
| 94 | + kfree(sg); | |
| 95 | + | |
| 96 | + return -ENOMEM; | |
| 97 | +} | |
| 98 | + | |
| 99 | +static void | |
| 100 | +iser_copy_bounce(struct iser_data_buf *data, bool to_buffer) | |
| 101 | +{ | |
| 102 | + struct scatterlist *osg, *bsg = data->sg; | |
| 103 | + void *oaddr, *baddr; | |
| 104 | + unsigned int left = data->data_len; | |
| 105 | + unsigned int bsg_off = 0; | |
| 106 | + int i; | |
| 107 | + | |
| 108 | + for_each_sg(data->orig_sg, osg, data->orig_size, i) { | |
| 109 | + unsigned int copy_len, osg_off = 0; | |
| 110 | + | |
| 111 | + oaddr = kmap_atomic(sg_page(osg)) + osg->offset; | |
| 112 | + copy_len = min(left, osg->length); | |
| 113 | + while (copy_len) { | |
| 114 | + unsigned int len = min(copy_len, bsg->length - bsg_off); | |
| 115 | + | |
| 116 | + baddr = kmap_atomic(sg_page(bsg)) + bsg->offset; | |
| 117 | + if (to_buffer) | |
| 118 | + memcpy(baddr + bsg_off, oaddr + osg_off, len); | |
| 119 | + else | |
| 120 | + memcpy(oaddr + osg_off, baddr + bsg_off, len); | |
| 121 | + | |
| 122 | + kunmap_atomic(baddr - bsg->offset); | |
| 123 | + osg_off += len; | |
| 124 | + bsg_off += len; | |
| 125 | + copy_len -= len; | |
| 126 | + | |
| 127 | + if (bsg_off >= bsg->length) { | |
| 128 | + bsg = sg_next(bsg); | |
| 129 | + bsg_off = 0; | |
| 130 | + } | |
| 87 | 131 | } |
| 132 | + kunmap_atomic(oaddr - osg->offset); | |
| 133 | + left -= osg_off; | |
| 88 | 134 | } |
| 135 | +} | |
| 136 | + | |
| 137 | +static inline void | |
| 138 | +iser_copy_from_bounce(struct iser_data_buf *data) | |
| 139 | +{ | |
| 140 | + iser_copy_bounce(data, false); | |
| 141 | +} | |
| 142 | + | |
| 143 | +static inline void | |
| 144 | +iser_copy_to_bounce(struct iser_data_buf *data) | |
| 145 | +{ | |
| 146 | + iser_copy_bounce(data, true); | |
| 147 | +} | |
| 148 | + | |
| 149 | +struct fast_reg_descriptor * | |
| 150 | +iser_reg_desc_get(struct ib_conn *ib_conn) | |
| 151 | +{ | |
| 152 | + struct fast_reg_descriptor *desc; | |
| 153 | + unsigned long flags; | |
| 154 | + | |
| 155 | + spin_lock_irqsave(&ib_conn->lock, flags); | |
| 156 | + desc = list_first_entry(&ib_conn->fastreg.pool, | |
| 157 | + struct fast_reg_descriptor, list); | |
| 158 | + list_del(&desc->list); | |
| 159 | + spin_unlock_irqrestore(&ib_conn->lock, flags); | |
| 160 | + | |
| 161 | + return desc; | |
| 162 | +} | |
| 163 | + | |
| 164 | +void | |
| 165 | +iser_reg_desc_put(struct ib_conn *ib_conn, | |
| 166 | + struct fast_reg_descriptor *desc) | |
| 167 | +{ | |
| 168 | + unsigned long flags; | |
| 89 | 169 | |
| 90 | − sg_init_one(&data_copy->sg_single, mem, cmd_data_len); | |
| 91 | − data_copy->buf = &data_copy->sg_single; | |
| 92 | − data_copy->size = 1; | |
| 93 | − data_copy->copy_buf = mem; | |
| 170 | + spin_lock_irqsave(&ib_conn->lock, flags); | |
| 171 | + list_add(&desc->list, &ib_conn->fastreg.pool); | |
| 172 | + spin_unlock_irqrestore(&ib_conn->lock, flags); | |
| 173 | +} | |
| 94 | 174 | |
| 95 | − dma_nents = ib_dma_map_sg(dev, &data_copy->sg_single, 1, | |
| 96 | − (cmd_dir == ISER_DIR_OUT) ? | |
| 97 | − DMA_TO_DEVICE : DMA_FROM_DEVICE); | |
| 98 | − BUG_ON(dma_nents == 0); | |
| 175 | +/** | |
| 176 | + * iser_start_rdma_unaligned_sg | |
| 177 | + */ | |
| 178 | +static int iser_start_rdma_unaligned_sg(struct iscsi_iser_task *iser_task, | |
| 179 | + struct iser_data_buf *data, | |
| 180 | + enum iser_data_dir cmd_dir) | |
| 181 | +{ | |
| 182 | + struct ib_device *dev = iser_task->iser_conn->ib_conn.device->ib_device; | |
| 183 | + int rc; | |
| 184 | + | |
| 185 | + rc = iser_alloc_bounce_sg(data); | |
| 186 | + if (rc) { | |
| 187 | + iser_err("Failed to allocate bounce for data len %lu\n", | |
| 188 | + data->data_len); | |
| 189 | + return rc; | |
| 190 | + } | |
| 191 | + | |
| 192 | + if (cmd_dir == ISER_DIR_OUT) | |
| 193 | + iser_copy_to_bounce(data); | |
| 99 | 194 | |
| 100 | − data_copy->dma_nents = dma_nents; | |
| 101 | − data_copy->data_len = cmd_data_len; | |
| 195 | + data->dma_nents = ib_dma_map_sg(dev, data->sg, data->size, | |
| 196 | + (cmd_dir == ISER_DIR_OUT) ? | |
| 197 | + DMA_TO_DEVICE : DMA_FROM_DEVICE); | |
| 198 | + if (!data->dma_nents) { | |
| 199 | + iser_err("Got dma_nents %d, something went wrong...\n", | |
| 200 | + data->dma_nents); | |
| 201 | + rc = -ENOMEM; | |
| 202 | + goto err; | |
| 203 | + } | |
| 102 | 204 | |
| 103 | 205 | return 0; |
| 206 | +err: | |
| 207 | + iser_free_bounce_sg(data); | |
| 208 | + return rc; | |
| 104 | 209 | } |
| 105 | 210 | |
| 106 | 211 | /** |
| @@ -109,51 +214,18 @@ static int iser_start_rdma_unaligned_sg(struct iscsi_iser_task *iser_task, · 2 unmodified lines | ||
| 109 | 214 | |
| 110 | 215 | void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_task *iser_task, |
| 111 | 216 | struct iser_data_buf *data, |
| 112 | − struct iser_data_buf *data_copy, | |
| 113 | 217 | enum iser_data_dir cmd_dir) |
| 114 | 218 | { |
| 115 | − struct ib_device *dev; | |
| 116 | − unsigned long cmd_data_len; | |
| 117 | − | |
| 118 | − dev = iser_task->iser_conn->ib_conn.device->ib_device; | |
| 219 | + struct ib_device *dev = iser_task->iser_conn->ib_conn.device->ib_device; | |
| 119 | 220 | |
| 120 | − ib_dma_unmap_sg(dev, &data_copy->sg_single, 1, | |
| 221 | + ib_dma_unmap_sg(dev, data->sg, data->size, | |
| 121 | 222 | (cmd_dir == ISER_DIR_OUT) ? |
| 122 | 223 | DMA_TO_DEVICE : DMA_FROM_DEVICE); |
| 123 | 224 | |
| 124 | − if (cmd_dir == ISER_DIR_IN) { | |
| 125 | − char *mem; | |
| 126 | − struct scatterlist *sgl, *sg; | |
| 127 | − unsigned char *p, *to; | |
| 128 | − unsigned int sg_size; | |
| 129 | − int i; | |
| 130 | − | |
| 131 | − /* copy back read RDMA to unaligned sg */ | |
| 132 | − mem = data_copy->copy_buf; | |
| 133 | − | |
| 134 | − sgl = (struct scatterlist *)data->buf; | |
| 135 | − sg_size = data->size; | |
| 136 | − | |
| 137 | − p = mem; | |
| 138 | − for_each_sg(sgl, sg, sg_size, i) { | |
| 139 | − to = kmap_atomic(sg_page(sg)); | |
| 140 | − memcpy(to + sg->offset, | |
| 141 | − p, | |
| 142 | − sg->length); | |
| 143 | − kunmap_atomic(to); | |
| 144 | − p += sg->length; | |
| 145 | − } | |
| 146 | − } | |
| 225 | + if (cmd_dir == ISER_DIR_IN) | |
| 226 | + iser_copy_from_bounce(data); | |
| 147 | 227 | |
| 148 | − cmd_data_len = data->data_len; | |
| 149 | − | |
| 150 | − if (cmd_data_len > ISER_KMALLOC_THRESHOLD) | |
| 151 | − free_pages((unsigned long)data_copy->copy_buf, | |
| 152 | − ilog2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT); | |
| 153 | − else | |
| 154 | − kfree(data_copy->copy_buf); | |
| 155 | − | |
| 156 | − data_copy->copy_buf = NULL; | |
| 228 | + iser_free_bounce_sg(data); | |
| 157 | 229 | } |
| 158 | 230 | |
| 159 | 231 | #define IS_4K_ALIGNED(addr) ((((unsigned long)addr) & ~MASK_4K) == 0) |
| @@ -175,7 +247,7 @@ static int iser_sg_to_page_vec(struct iser_data_buf *data, · 15 unmodified lines | ||
| 175 | 247 | struct ib_device *ibdev, u64 *pages, |
| 176 | 248 | int *offset, int *data_size) |
| 177 | 249 | { |
| 178 | − struct scatterlist *sg, *sgl = (struct scatterlist *)data->buf; | |
| 250 | + struct scatterlist *sg, *sgl = data->sg; | |
| 179 | 251 | u64 start_addr, end_addr, page, chunk_start = 0; |
| 180 | 252 | unsigned long total_sz = 0; |
| 181 | 253 | unsigned int dma_len; |
| @@ -227,14 +299,14 @@ static int iser_sg_to_page_vec(struct iser_data_buf *data, · 45 unmodified lines | ||
| 227 | 299 | static int iser_data_buf_aligned_len(struct iser_data_buf *data, |
| 228 | 300 | struct ib_device *ibdev) |
| 229 | 301 | { |
| 230 | − struct scatterlist *sgl, *sg, *next_sg = NULL; | |
| 302 | + struct scatterlist *sg, *sgl, *next_sg = NULL; | |
| 231 | 303 | u64 start_addr, end_addr; |
| 232 | 304 | int i, ret_len, start_check = 0; |
| 233 | 305 | |
| 234 | 306 | if (data->dma_nents == 1) |
| 235 | 307 | return 1; |
| 236 | 308 | |
| 237 | − sgl = (struct scatterlist *)data->buf; | |
| 309 | + sgl = data->sg; | |
| 238 | 310 | start_addr = ib_sg_dma_address(ibdev, sgl); |
| 239 | 311 | |
| 240 | 312 | for_each_sg(sgl, sg, data->dma_nents, i) { |
| @@ -266,11 +338,10 @@ static int iser_data_buf_aligned_len(struct iser_data_buf *data, · 25 unmodified lines | ||
| 266 | 338 | static void iser_data_buf_dump(struct iser_data_buf *data, |
| 267 | 339 | struct ib_device *ibdev) |
| 268 | 340 | { |
| 269 | − struct scatterlist *sgl = (struct scatterlist *)data->buf; | |
| 270 | 341 | struct scatterlist *sg; |
| 271 | 342 | int i; |
| 272 | 343 | |
| 273 | − for_each_sg(sgl, sg, data->dma_nents, i) | |
| 344 | + for_each_sg(data->sg, sg, data->dma_nents, i) | |
| 274 | 345 | iser_dbg("sg[%d] dma_addr:0x%lX page:0x%p " |
| 275 | 346 | "off:0x%x sz:0x%x dma_len:0x%x\n", |
| 276 | 347 | i, (unsigned long)ib_sg_dma_address(ibdev, sg), |
| @@ -288,31 +359,6 @@ static void iser_dump_page_vec(struct iser_page_vec *page_vec) · 11 unmodified lines | ||
| 288 | 359 | iser_err("%d %lx\n",i,(unsigned long)page_vec->pages[i]); |
| 289 | 360 | } |
| 290 | 361 | |
| 291 | −static void iser_page_vec_build(struct iser_data_buf *data, | |
| 292 | − struct iser_page_vec *page_vec, | |
| 293 | − struct ib_device *ibdev) | |
| 294 | −{ | |
| 295 | − int page_vec_len = 0; | |
| 296 | − | |
| 297 | − page_vec->length = 0; | |
| 298 | − page_vec->offset = 0; | |
| 299 | − | |
| 300 | − iser_dbg("Translating sg sz: %d\n", data->dma_nents); | |
| 301 | − page_vec_len = iser_sg_to_page_vec(data, ibdev, page_vec->pages, | |
| 302 | − &page_vec->offset, | |
| 303 | − &page_vec->data_size); | |
| 304 | − iser_dbg("sg len %d page_vec_len %d\n", data->dma_nents, page_vec_len); | |
| 305 | − | |
| 306 | − page_vec->length = page_vec_len; | |
| 307 | − | |
| 308 | − if (page_vec_len * SIZE_4K < page_vec->data_size) { | |
| 309 | − iser_err("page_vec too short to hold this SG\n"); | |
| 310 | − iser_data_buf_dump(data, ibdev); | |
| 311 | − iser_dump_page_vec(page_vec); | |
| 312 | − BUG(); | |
| 313 | − } | |
| 314 | −} | |
| 315 | − | |
| 316 | 362 | int iser_dma_map_task_data(struct iscsi_iser_task *iser_task, |
| 317 | 363 | struct iser_data_buf *data, |
| 318 | 364 | enum iser_data_dir iser_dir, |
| @@ -323,7 +369,7 @@ int iser_dma_map_task_data(struct iscsi_iser_task *iser_task, · 4 unmodified lines | ||
| 323 | 369 | iser_task->dir[iser_dir] = 1; |
| 324 | 370 | dev = iser_task->iser_conn->ib_conn.device->ib_device; |
| 325 | 371 | |
| 326 | − data->dma_nents = ib_dma_map_sg(dev, data->buf, data->size, dma_dir); | |
| 372 | + data->dma_nents = ib_dma_map_sg(dev, data->sg, data->size, dma_dir); | |
| 327 | 373 | if (data->dma_nents == 0) { |
| 328 | 374 | iser_err("dma_map_sg failed!!!\n"); |
| 329 | 375 | return -EINVAL; |
| @@ -338,24 +384,41 @@ void iser_dma_unmap_task_data(struct iscsi_iser_task *iser_task, · 8 unmodified lines | ||
| 338 | 384 | struct ib_device *dev; |
| 339 | 385 | |
| 340 | 386 | dev = iser_task->iser_conn->ib_conn.device->ib_device; |
| 341 | − ib_dma_unmap_sg(dev, data->buf, data->size, dir); | |
| 387 | + ib_dma_unmap_sg(dev, data->sg, data->size, dir); | |
| 388 | +} | |
| 389 | + | |
| 390 | +static int | |
| 391 | +iser_reg_dma(struct iser_device *device, struct iser_data_buf *mem, | |
| 392 | + struct iser_mem_reg *reg) | |
| 393 | +{ | |
| 394 | + struct scatterlist *sg = mem->sg; | |
| 395 | + | |
| 396 | + reg->sge.lkey = device->mr->lkey; | |
| 397 | + reg->rkey = device->mr->rkey; | |
| 398 | + reg->sge.addr = ib_sg_dma_address(device->ib_device, &sg[0]); | |
| 399 | + reg->sge.length = ib_sg_dma_len(device->ib_device, &sg[0]); | |
| 400 | + | |
| 401 | + iser_dbg("Single DMA entry: lkey=0x%x, rkey=0x%x, addr=0x%llx," | |
| 402 | + " length=0x%x\n", reg->sge.lkey, reg->rkey, | |
| 403 | + reg->sge.addr, reg->sge.length); | |
| 404 | + | |
| 405 | + return 0; | |
| 342 | 406 | } |
| 343 | 407 | |
| 344 | 408 | static int fall_to_bounce_buf(struct iscsi_iser_task *iser_task, |
| 345 | − struct ib_device *ibdev, | |
| 346 | 409 | struct iser_data_buf *mem, |
| 347 | − struct iser_data_buf *mem_copy, | |
| 348 | 410 | enum iser_data_dir cmd_dir, |
| 349 | 411 | int aligned_len) |
| 350 | 412 | { |
| 351 | − struct iscsi_conn *iscsi_conn = iser_task->iser_conn->iscsi_conn; | |
| 413 | + struct iscsi_conn *iscsi_conn = iser_task->iser_conn->iscsi_conn; | |
| 414 | + struct iser_device *device = iser_task->iser_conn->ib_conn.device; | |
| 352 | 415 | |
| 353 | 416 | iscsi_conn->fmr_unalign_cnt++; |
| 354 | 417 | iser_warn("rdma alignment violation (%d/%d aligned) or FMR not supported\n", |
| 355 | 418 | aligned_len, mem->size); |
| 356 | 419 | |
| 357 | 420 | if (iser_debug_level > 0) |
| 358 | − iser_data_buf_dump(mem, ibdev); | |
| 421 | + iser_data_buf_dump(mem, device->ib_device); | |
| 359 | 422 | |
| 360 | 423 | /* unmap the command data before accessing it */ |
| 361 | 424 | iser_dma_unmap_task_data(iser_task, mem, |
| @@ -364,12 +427,94 @@ static int fall_to_bounce_buf(struct iscsi_iser_task *iser_task, · 2 unmodified lines | ||
| 364 | 427 | |
| 365 | 428 | /* allocate copy buf, if we are writing, copy the */ |
| 366 | 429 | /* unaligned scatterlist, dma map the copy */ |
| 367 | − if (iser_start_rdma_unaligned_sg(iser_task, mem, mem_copy, cmd_dir) != 0) | |
| 430 | + if (iser_start_rdma_unaligned_sg(iser_task, mem, cmd_dir) != 0) | |
| 368 | 431 | return -ENOMEM; |
| 369 | 432 | |
| 370 | 433 | return 0; |
| 371 | 434 | } |
| 372 | 435 | |
| 436 | +/** | |
| 437 | + * iser_reg_page_vec - Register physical memory | |
| 438 | + * | |
| 439 | + * returns: 0 on success, errno code on failure | |
| 440 | + */ | |
| 441 | +static | |
| 442 | +int iser_reg_page_vec(struct iscsi_iser_task *iser_task, | |
| 443 | + struct iser_data_buf *mem, | |
| 444 | + struct iser_page_vec *page_vec, | |
| 445 | + struct iser_mem_reg *mem_reg) | |
| 446 | +{ | |
| 447 | + struct ib_conn *ib_conn = &iser_task->iser_conn->ib_conn; | |
| 448 | + struct iser_device *device = ib_conn->device; | |
| 449 | + struct ib_pool_fmr *fmr; | |
| 450 | + int ret, plen; | |
| 451 | + | |
| 452 | + plen = iser_sg_to_page_vec(mem, device->ib_device, | |
| 453 | + page_vec->pages, | |
| 454 | + &page_vec->offset, | |
| 455 | + &page_vec->data_size); | |
| 456 | + page_vec->length = plen; | |
| 457 | + if (plen * SIZE_4K < page_vec->data_size) { | |
| 458 | + iser_err("page vec too short to hold this SG\n"); | |
| 459 | + iser_data_buf_dump(mem, device->ib_device); | |
| 460 | + iser_dump_page_vec(page_vec); | |
| 461 | + return -EINVAL; | |
| 462 | + } | |
| 463 | + | |
| 464 | + fmr = ib_fmr_pool_map_phys(ib_conn->fmr.pool, | |
| 465 | + page_vec->pages, | |
| 466 | + page_vec->length, | |
| 467 | + page_vec->pages[0]); | |
| 468 | + if (IS_ERR(fmr)) { | |
| 469 | + ret = PTR_ERR(fmr); | |
| 470 | + iser_err("ib_fmr_pool_map_phys failed: %d\n", ret); | |
| 471 | + return ret; | |
| 472 | + } | |
| 473 | + | |
| 474 | + mem_reg->sge.lkey = fmr->fmr->lkey; | |
| 475 | + mem_reg->rkey = fmr->fmr->rkey; | |
| 476 | + mem_reg->sge.addr = page_vec->pages[0] + page_vec->offset; | |
| 477 | + mem_reg->sge.length = page_vec->data_size; | |
| 478 | + mem_reg->mem_h = fmr; | |
| 479 | + | |
| 480 | + return 0; | |
| 481 | +} | |
| 482 | + | |
| 483 | +/** | |
| 484 | + * Unregister (previosuly registered using FMR) memory. | |
| 485 | + * If memory is non-FMR does nothing. | |
| 486 | + */ | |
| 487 | +void iser_unreg_mem_fmr(struct iscsi_iser_task *iser_task, | |
| 488 | + enum iser_data_dir cmd_dir) | |
| 489 | +{ | |
| 490 | + struct iser_mem_reg *reg = &iser_task->rdma_reg[cmd_dir]; | |
| 491 | + int ret; | |
| 492 | + | |
| 493 | + if (!reg->mem_h) | |
| 494 | + return; | |
| 495 | + | |
| 496 | + iser_dbg("PHYSICAL Mem.Unregister mem_h %p\n", reg->mem_h); | |
| 497 | + | |
| 498 | + ret = ib_fmr_pool_unmap((struct ib_pool_fmr *)reg->mem_h); | |
| 499 | + if (ret) | |
| 500 | + iser_err("ib_fmr_pool_unmap failed %d\n", ret); | |
| 501 | + | |
| 502 | + reg->mem_h = NULL; | |
| 503 | +} | |
| 504 | + | |
| 505 | +void iser_unreg_mem_fastreg(struct iscsi_iser_task *iser_task, | |
| 506 | + enum iser_data_dir cmd_dir) | |
| 507 | +{ | |
| 508 | + struct iser_mem_reg *reg = &iser_task->rdma_reg[cmd_dir]; | |
| 509 | + | |
| 510 | + if (!reg->mem_h) | |
| 511 | + return; | |
| 512 | + | |
| 513 | + iser_reg_desc_put(&iser_task->iser_conn->ib_conn, | |
| 514 | + reg->mem_h); | |
| 515 | + reg->mem_h = NULL; | |
| 516 | +} | |
| 517 | + | |
| 373 | 518 | /** |
| 374 | 519 | * iser_reg_rdma_mem_fmr - Registers memory intended for RDMA, |
| 375 | 520 | * using FMR (if possible) obtaining rkey and va |
| @@ -383,45 +528,29 @@ int iser_reg_rdma_mem_fmr(struct iscsi_iser_task *iser_task, · 7 unmodified lines | ||
| 383 | 528 | struct iser_device *device = ib_conn->device; |
| 384 | 529 | struct ib_device *ibdev = device->ib_device; |
| 385 | 530 | struct iser_data_buf *mem = &iser_task->data[cmd_dir]; |
| 386 | − struct iser_regd_buf *regd_buf; | |
| 531 | + struct iser_mem_reg *mem_reg; | |
| 387 | 532 | int aligned_len; |
| 388 | 533 | int err; |
| 389 | 534 | int i; |
| 390 | − struct scatterlist *sg; | |
| 391 | 535 | |
| 392 | − regd_buf = &iser_task->rdma_regd[cmd_dir]; | |
| 536 | + mem_reg = &iser_task->rdma_reg[cmd_dir]; | |
| 393 | 537 | |
| 394 | 538 | aligned_len = iser_data_buf_aligned_len(mem, ibdev); |
| 395 | 539 | if (aligned_len != mem->dma_nents) { |
| 396 | − err = fall_to_bounce_buf(iser_task, ibdev, mem, | |
| 397 | − &iser_task->data_copy[cmd_dir], | |
| 540 | + err = fall_to_bounce_buf(iser_task, mem, | |
| 398 | 541 | cmd_dir, aligned_len); |
| 399 | 542 | if (err) { |
| 400 | 543 | iser_err("failed to allocate bounce buffer\n"); |
| 401 | 544 | return err; |
| 402 | 545 | } |
| 403 | − mem = &iser_task->data_copy[cmd_dir]; | |
| 404 | 546 | } |
| 405 | 547 | |
| 406 | 548 | /* if there a single dma entry, FMR is not needed */ |
| 407 | 549 | if (mem->dma_nents == 1) { |
| 408 | − sg = (struct scatterlist *)mem->buf; | |
| 409 | − | |
| 410 | − regd_buf->reg.lkey = device->mr->lkey; | |
| 411 | − regd_buf->reg.rkey = device->mr->rkey; | |
| 412 | − regd_buf->reg.len = ib_sg_dma_len(ibdev, &sg[0]); | |
| 413 | − regd_buf->reg.va = ib_sg_dma_address(ibdev, &sg[0]); | |
| 414 | − | |
| 415 | − iser_dbg("PHYSICAL Mem.register: lkey: 0x%08X rkey: 0x%08X " | |
| 416 | − "va: 0x%08lX sz: %ld]\n", | |
| 417 | − (unsigned int)regd_buf->reg.lkey, | |
| 418 | − (unsigned int)regd_buf->reg.rkey, | |
| 419 | − (unsigned long)regd_buf->reg.va, | |
| 420 | − (unsigned long)regd_buf->reg.len); | |
| 550 | + return iser_reg_dma(device, mem, mem_reg); | |
| 421 | 551 | } else { /* use FMR for multiple dma entries */ |
| 422 | − iser_page_vec_build(mem, ib_conn->fmr.page_vec, ibdev); | |
| 423 | − err = iser_reg_page_vec(ib_conn, ib_conn->fmr.page_vec, | |
| 424 | − ®d_buf->reg); | |
| 552 | + err = iser_reg_page_vec(iser_task, mem, ib_conn->fmr.page_vec, | |
| 553 | + mem_reg); | |
| 425 | 554 | if (err && err != -EAGAIN) { |
| 426 | 555 | iser_data_buf_dump(mem, ibdev); |
| 427 | 556 | iser_err("mem->dma_nents = %d (dlength = 0x%x)\n", |
| @@ -519,8 +648,10 @@ iser_inv_rkey(struct ib_send_wr *inv_wr, struct ib_mr *mr) · 91 unmodified lines | ||
| 519 | 648 | |
| 520 | 649 | static int |
| 521 | 650 | iser_reg_sig_mr(struct iscsi_iser_task *iser_task, |
| 522 | − struct fast_reg_descriptor *desc, struct ib_sge *data_sge, | |
| 523 | − struct ib_sge *prot_sge, struct ib_sge *sig_sge) | |
| 651 | + struct fast_reg_descriptor *desc, | |
| 652 | + struct iser_mem_reg *data_reg, | |
| 653 | + struct iser_mem_reg *prot_reg, | |
| 654 | + struct iser_mem_reg *sig_reg) | |
| 524 | 655 | { |
| 525 | 656 | struct ib_conn *ib_conn = &iser_task->iser_conn->ib_conn; |
| 526 | 657 | struct iser_pi_context *pi_ctx = desc->pi_ctx; |
| @@ -544,12 +675,12 @@ iser_reg_sig_mr(struct iscsi_iser_task *iser_task, · 17 unmodified lines | ||
| 544 | 675 | memset(&sig_wr, 0, sizeof(sig_wr)); |
| 545 | 676 | sig_wr.opcode = IB_WR_REG_SIG_MR; |
| 546 | 677 | sig_wr.wr_id = ISER_FASTREG_LI_WRID; |
| 547 | − sig_wr.sg_list = data_sge; | |
| 678 | + sig_wr.sg_list = &data_reg->sge; | |
| 548 | 679 | sig_wr.num_sge = 1; |
| 549 | 680 | sig_wr.wr.sig_handover.sig_attrs = &sig_attrs; |
| 550 | 681 | sig_wr.wr.sig_handover.sig_mr = pi_ctx->sig_mr; |
| 551 | 682 | if (scsi_prot_sg_count(iser_task->sc)) |
| 552 | − sig_wr.wr.sig_handover.prot = prot_sge; | |
| 683 | + sig_wr.wr.sig_handover.prot = &prot_reg->sge; | |
| 553 | 684 | sig_wr.wr.sig_handover.access_flags = IB_ACCESS_LOCAL_WRITE | |
| 554 | 685 | IB_ACCESS_REMOTE_READ | |
| 555 | 686 | IB_ACCESS_REMOTE_WRITE; |
| @@ -566,27 +697,26 @@ iser_reg_sig_mr(struct iscsi_iser_task *iser_task, · 10 unmodified lines | ||
| 566 | 697 | } |
| 567 | 698 | desc->reg_indicators &= ~ISER_SIG_KEY_VALID; |
| 568 | 699 | |
| 569 | − sig_sge->lkey = pi_ctx->sig_mr->lkey; | |
| 570 | − sig_sge->addr = 0; | |
| 571 | − sig_sge->length = scsi_transfer_length(iser_task->sc); | |
| 700 | + sig_reg->sge.lkey = pi_ctx->sig_mr->lkey; | |
| 701 | + sig_reg->rkey = pi_ctx->sig_mr->rkey; | |
| 702 | + sig_reg->sge.addr = 0; | |
| 703 | + sig_reg->sge.length = scsi_transfer_length(iser_task->sc); | |
| 572 | 704 | |
| 573 | − iser_dbg("sig_sge: addr: 0x%llx length: %u lkey: 0x%x\n", | |
| 574 | − sig_sge->addr, sig_sge->length, | |
| 575 | − sig_sge->lkey); | |
| 705 | + iser_dbg("sig_sge: lkey: 0x%x, rkey: 0x%x, addr: 0x%llx, length: %u\n", | |
| 706 | + sig_reg->sge.lkey, sig_reg->rkey, sig_reg->sge.addr, | |
| 707 | + sig_reg->sge.length); | |
| 576 | 708 | err: |
| 577 | 709 | return ret; |
| 578 | 710 | } |
| 579 | 711 | |
| 580 | 712 | static int iser_fast_reg_mr(struct iscsi_iser_task *iser_task, |
| 581 | − struct iser_regd_buf *regd_buf, | |
| 582 | 713 | struct iser_data_buf *mem, |
| 714 | + struct fast_reg_descriptor *desc, | |
| 583 | 715 | enum iser_reg_indicator ind, |
| 584 | − struct ib_sge *sge) | |
| 716 | + struct iser_mem_reg *reg) | |
| 585 | 717 | { |
| 586 | − struct fast_reg_descriptor *desc = regd_buf->reg.mem_h; | |
| 587 | 718 | struct ib_conn *ib_conn = &iser_task->iser_conn->ib_conn; |
| 588 | 719 | struct iser_device *device = ib_conn->device; |
| 589 | − struct ib_device *ibdev = device->ib_device; | |
| 590 | 720 | struct ib_mr *mr; |
| 591 | 721 | struct ib_fast_reg_page_list *frpl; |
| 592 | 722 | struct ib_send_wr fastreg_wr, inv_wr; |
| @@ -594,17 +724,8 @@ static int iser_fast_reg_mr(struct iscsi_iser_task *iser_task, · 1 unmodified line | ||
| 594 | 724 | int ret, offset, size, plen; |
| 595 | 725 | |
| 596 | 726 | /* if there a single dma entry, dma mr suffices */ |
| 597 | − if (mem->dma_nents == 1) { | |
| 598 | − struct scatterlist *sg = (struct scatterlist *)mem->buf; | |
| 599 | − | |
| 600 | − sge->lkey = device->mr->lkey; | |
| 601 | − sge->addr = ib_sg_dma_address(ibdev, &sg[0]); | |
| 602 | − sge->length = ib_sg_dma_len(ibdev, &sg[0]); | |
| 603 | − | |
| 604 | − iser_dbg("Single DMA entry: lkey=0x%x, addr=0x%llx, length=0x%x\n", | |
| 605 | − sge->lkey, sge->addr, sge->length); | |
| 606 | − return 0; | |
| 607 | − } | |
| 727 | + if (mem->dma_nents == 1) | |
| 728 | + return iser_reg_dma(device, mem, reg); | |
| 608 | 729 | |
| 609 | 730 | if (ind == ISER_DATA_KEY_VALID) { |
| 610 | 731 | mr = desc->data_mr; |
| @@ -652,9 +773,10 @@ static int iser_fast_reg_mr(struct iscsi_iser_task *iser_task, · 41 unmodified lines | ||
| 652 | 773 | } |
| 653 | 774 | desc->reg_indicators &= ~ind; |
| 654 | 775 | |
| 655 | − sge->lkey = mr->lkey; | |
| 656 | − sge->addr = frpl->page_list[0] + offset; | |
| 657 | − sge->length = size; | |
| 776 | + reg->sge.lkey = mr->lkey; | |
| 777 | + reg->rkey = mr->rkey; | |
| 778 | + reg->sge.addr = frpl->page_list[0] + offset; | |
| 779 | + reg->sge.length = size; | |
| 658 | 780 | |
| 659 | 781 | return ret; |
| 660 | 782 | } |
| @@ -672,93 +794,66 @@ int iser_reg_rdma_mem_fastreg(struct iscsi_iser_task *iser_task, · 11 unmodified lines | ||
| 672 | 794 | struct iser_device *device = ib_conn->device; |
| 673 | 795 | struct ib_device *ibdev = device->ib_device; |
| 674 | 796 | struct iser_data_buf *mem = &iser_task->data[cmd_dir]; |
| 675 | − struct iser_regd_buf *regd_buf = &iser_task->rdma_regd[cmd_dir]; | |
| 797 | + struct iser_mem_reg *mem_reg = &iser_task->rdma_reg[cmd_dir]; | |
| 676 | 798 | struct fast_reg_descriptor *desc = NULL; |
| 677 | − struct ib_sge data_sge; | |
| 678 | 799 | int err, aligned_len; |
| 679 | − unsigned long flags; | |
| 680 | 800 | |
| 681 | 801 | aligned_len = iser_data_buf_aligned_len(mem, ibdev); |
| 682 | 802 | if (aligned_len != mem->dma_nents) { |
| 683 | − err = fall_to_bounce_buf(iser_task, ibdev, mem, | |
| 684 | − &iser_task->data_copy[cmd_dir], | |
| 803 | + err = fall_to_bounce_buf(iser_task, mem, | |
| 685 | 804 | cmd_dir, aligned_len); |
| 686 | 805 | if (err) { |
| 687 | 806 | iser_err("failed to allocate bounce buffer\n"); |
| 688 | 807 | return err; |
| 689 | 808 | } |
| 690 | − mem = &iser_task->data_copy[cmd_dir]; | |
| 691 | 809 | } |
| 692 | 810 | |
| 693 | 811 | if (mem->dma_nents != 1 || |
| 694 | 812 | scsi_get_prot_op(iser_task->sc) != SCSI_PROT_NORMAL) { |
| 695 | − spin_lock_irqsave(&ib_conn->lock, flags); | |
| 696 | − desc = list_first_entry(&ib_conn->fastreg.pool, | |
| 697 | − struct fast_reg_descriptor, list); | |
| 698 | − list_del(&desc->list); | |
| 699 | − spin_unlock_irqrestore(&ib_conn->lock, flags); | |
| 700 | − regd_buf->reg.mem_h = desc; | |
| 813 | + desc = iser_reg_desc_get(ib_conn); | |
| 814 | + mem_reg->mem_h = desc; | |
| 701 | 815 | } |
| 702 | 816 | |
| 703 | − err = iser_fast_reg_mr(iser_task, regd_buf, mem, | |
| 704 | − ISER_DATA_KEY_VALID, &data_sge); | |
| 817 | + err = iser_fast_reg_mr(iser_task, mem, desc, | |
| 818 | + ISER_DATA_KEY_VALID, mem_reg); | |
| 705 | 819 | if (err) |
| 706 | 820 | goto err_reg; |
| 707 | 821 | |
| 708 | 822 | if (scsi_get_prot_op(iser_task->sc) != SCSI_PROT_NORMAL) { |
| 709 | − struct ib_sge prot_sge, sig_sge; | |
| 823 | + struct iser_mem_reg prot_reg; | |
| 710 | 824 | |
| 711 | − memset(&prot_sge, 0, sizeof(prot_sge)); | |
| 825 | + memset(&prot_reg, 0, sizeof(prot_reg)); | |
| 712 | 826 | if (scsi_prot_sg_count(iser_task->sc)) { |
| 713 | 827 | mem = &iser_task->prot[cmd_dir]; |
| 714 | 828 | aligned_len = iser_data_buf_aligned_len(mem, ibdev); |
| 715 | 829 | if (aligned_len != mem->dma_nents) { |
| 716 | − err = fall_to_bounce_buf(iser_task, ibdev, mem, | |
| 717 | − &iser_task->prot_copy[cmd_dir], | |
| 830 | + err = fall_to_bounce_buf(iser_task, mem, | |
| 718 | 831 | cmd_dir, aligned_len); |
| 719 | 832 | if (err) { |
| 720 | 833 | iser_err("failed to allocate bounce buffer\n"); |
| 721 | 834 | return err; |
| 722 | 835 | } |
| 723 | − mem = &iser_task->prot_copy[cmd_dir]; | |
| 724 | 836 | } |
| 725 | 837 | |
| 726 | − err = iser_fast_reg_mr(iser_task, regd_buf, mem, | |
| 727 | − ISER_PROT_KEY_VALID, &prot_sge); | |
| 838 | + err = iser_fast_reg_mr(iser_task, mem, desc, | |
| 839 | + ISER_PROT_KEY_VALID, &prot_reg); | |
| 728 | 840 | if (err) |
| 729 | 841 | goto err_reg; |
| 730 | 842 | } |
| 731 | 843 | |
| 732 | − err = iser_reg_sig_mr(iser_task, desc, &data_sge, | |
| 733 | − &prot_sge, &sig_sge); | |
| 844 | + err = iser_reg_sig_mr(iser_task, desc, mem_reg, | |
| 845 | + &prot_reg, mem_reg); | |
| 734 | 846 | if (err) { |
| 735 | 847 | iser_err("Failed to register signature mr\n"); |
| 736 | 848 | return err; |
| 737 | 849 | } |
| 738 | 850 | desc->reg_indicators |= ISER_FASTREG_PROTECTED; |
| 739 | − | |
| 740 | − regd_buf->reg.lkey = sig_sge.lkey; | |
| 741 | − regd_buf->reg.rkey = desc->pi_ctx->sig_mr->rkey; | |
| 742 | − regd_buf->reg.va = sig_sge.addr; | |
| 743 | − regd_buf->reg.len = sig_sge.length; | |
| 744 | − } else { | |
| 745 | − if (desc) | |
| 746 | − regd_buf->reg.rkey = desc->data_mr->rkey; | |
| 747 | − else | |
| 748 | − regd_buf->reg.rkey = device->mr->rkey; | |
| 749 | − | |
| 750 | − regd_buf->reg.lkey = data_sge.lkey; | |
| 751 | − regd_buf->reg.va = data_sge.addr; | |
| 752 | − regd_buf->reg.len = data_sge.length; | |
| 753 | 851 | } |
| 754 | 852 | |
| 755 | 853 | return 0; |
| 756 | 854 | err_reg: |
| 757 | − if (desc) { | |
| 758 | − spin_lock_irqsave(&ib_conn->lock, flags); | |
| 759 | − list_add_tail(&desc->list, &ib_conn->fastreg.pool); | |
| 760 | − spin_unlock_irqrestore(&ib_conn->lock, flags); | |
| 761 | − } | |
| 855 | + if (desc) | |
| 856 | + iser_reg_desc_put(ib_conn, desc); | |
| 762 | 857 | |
| 763 | 858 | return err; |
| 764 | 859 | } |
| @@ -273,6 +273,65 @@ void iser_free_fmr_pool(struct ib_conn *ib_conn) · 272 unmodified lines | ||
| 273 | 273 | ib_conn->fmr.page_vec = NULL; |
| 274 | 274 | } |
| 275 | 275 | |
| 276 | +static int | |
| 277 | +iser_alloc_pi_ctx(struct ib_device *ib_device, struct ib_pd *pd, | |
| 278 | + struct fast_reg_descriptor *desc) | |
| 279 | +{ | |
| 280 | + struct iser_pi_context *pi_ctx = NULL; | |
| 281 | + struct ib_mr_init_attr mr_init_attr = {.max_reg_descriptors = 2, | |
| 282 | + .flags = IB_MR_SIGNATURE_EN}; | |
| 283 | + int ret = 0; | |
| 284 | + | |
| 285 | + desc->pi_ctx = kzalloc(sizeof(*desc->pi_ctx), GFP_KERNEL); | |
| 286 | + if (!desc->pi_ctx) | |
| 287 | + return -ENOMEM; | |
| 288 | + | |
| 289 | + pi_ctx = desc->pi_ctx; | |
| 290 | + | |
| 291 | + pi_ctx->prot_frpl = ib_alloc_fast_reg_page_list(ib_device, | |
| 292 | + ISCSI_ISER_SG_TABLESIZE); | |
| 293 | + if (IS_ERR(pi_ctx->prot_frpl)) { | |
| 294 | + ret = PTR_ERR(pi_ctx->prot_frpl); | |
| 295 | + goto prot_frpl_failure; | |
| 296 | + } | |
| 297 | + | |
| 298 | + pi_ctx->prot_mr = ib_alloc_fast_reg_mr(pd, | |
| 299 | + ISCSI_ISER_SG_TABLESIZE + 1); | |
| 300 | + if (IS_ERR(pi_ctx->prot_mr)) { | |
| 301 | + ret = PTR_ERR(pi_ctx->prot_mr); | |
| 302 | + goto prot_mr_failure; | |
| 303 | + } | |
| 304 | + desc->reg_indicators |= ISER_PROT_KEY_VALID; | |
| 305 | + | |
| 306 | + pi_ctx->sig_mr = ib_create_mr(pd, &mr_init_attr); | |
| 307 | + if (IS_ERR(pi_ctx->sig_mr)) { | |
| 308 | + ret = PTR_ERR(pi_ctx->sig_mr); | |
| 309 | + goto sig_mr_failure; | |
| 310 | + } | |
| 311 | + desc->reg_indicators |= ISER_SIG_KEY_VALID; | |
| 312 | + desc->reg_indicators &= ~ISER_FASTREG_PROTECTED; | |
| 313 | + | |
| 314 | + return 0; | |
| 315 | + | |
| 316 | +sig_mr_failure: | |
| 317 | + ib_dereg_mr(desc->pi_ctx->prot_mr); | |
| 318 | +prot_mr_failure: | |
| 319 | + ib_free_fast_reg_page_list(desc->pi_ctx->prot_frpl); | |
| 320 | +prot_frpl_failure: | |
| 321 | + kfree(desc->pi_ctx); | |
| 322 | + | |
| 323 | + return ret; | |
| 324 | +} | |
| 325 | + | |
| 326 | +static void | |
| 327 | +iser_free_pi_ctx(struct iser_pi_context *pi_ctx) | |
| 328 | +{ | |
| 329 | + ib_free_fast_reg_page_list(pi_ctx->prot_frpl); | |
| 330 | + ib_dereg_mr(pi_ctx->prot_mr); | |
| 331 | + ib_destroy_mr(pi_ctx->sig_mr); | |
| 332 | + kfree(pi_ctx); | |
| 333 | +} | |
| 334 | + | |
| 276 | 335 | static int |
| 277 | 336 | iser_create_fastreg_desc(struct ib_device *ib_device, struct ib_pd *pd, |
| 278 | 337 | bool pi_enable, struct fast_reg_descriptor *desc) |
| @@ -297,59 +356,12 @@ iser_create_fastreg_desc(struct ib_device *ib_device, struct ib_pd *pd, · 18 unmodified lines | ||
| 297 | 356 | desc->reg_indicators |= ISER_DATA_KEY_VALID; |
| 298 | 357 | |
| 299 | 358 | if (pi_enable) { |
| 300 | − struct ib_mr_init_attr mr_init_attr = {0}; | |
| 301 | − struct iser_pi_context *pi_ctx = NULL; | |
| 302 | − | |
| 303 | − desc->pi_ctx = kzalloc(sizeof(*desc->pi_ctx), GFP_KERNEL); | |
| 304 | − if (!desc->pi_ctx) { | |
| 305 | − iser_err("Failed to allocate pi context\n"); | |
| 306 | − ret = -ENOMEM; | |
| 359 | + ret = iser_alloc_pi_ctx(ib_device, pd, desc); | |
| 360 | + if (ret) | |
| 307 | 361 | goto pi_ctx_alloc_failure; |
| 308 | − } | |
| 309 | − pi_ctx = desc->pi_ctx; | |
| 310 | − | |
| 311 | − pi_ctx->prot_frpl = ib_alloc_fast_reg_page_list(ib_device, | |
| 312 | − ISCSI_ISER_SG_TABLESIZE); | |
| 313 | − if (IS_ERR(pi_ctx->prot_frpl)) { | |
| 314 | − ret = PTR_ERR(pi_ctx->prot_frpl); | |
| 315 | − iser_err("Failed to allocate prot frpl ret=%d\n", | |
| 316 | − ret); | |
| 317 | − goto prot_frpl_failure; | |
| 318 | − } | |
| 319 | − | |
| 320 | − pi_ctx->prot_mr = ib_alloc_fast_reg_mr(pd, | |
| 321 | − ISCSI_ISER_SG_TABLESIZE + 1); | |
| 322 | − if (IS_ERR(pi_ctx->prot_mr)) { | |
| 323 | − ret = PTR_ERR(pi_ctx->prot_mr); | |
| 324 | − iser_err("Failed to allocate prot frmr ret=%d\n", | |
| 325 | − ret); | |
| 326 | − goto prot_mr_failure; | |
| 327 | − } | |
| 328 | − desc->reg_indicators |= ISER_PROT_KEY_VALID; | |
| 329 | − | |
| 330 | − mr_init_attr.max_reg_descriptors = 2; | |
| 331 | − mr_init_attr.flags |= IB_MR_SIGNATURE_EN; | |
| 332 | − pi_ctx->sig_mr = ib_create_mr(pd, &mr_init_attr); | |
| 333 | − if (IS_ERR(pi_ctx->sig_mr)) { | |
| 334 | − ret = PTR_ERR(pi_ctx->sig_mr); | |
| 335 | − iser_err("Failed to allocate signature enabled mr err=%d\n", | |
| 336 | − ret); | |
| 337 | − goto sig_mr_failure; | |
| 338 | − } | |
| 339 | − desc->reg_indicators |= ISER_SIG_KEY_VALID; | |
| 340 | 362 | } |
| 341 | − desc->reg_indicators &= ~ISER_FASTREG_PROTECTED; | |
| 342 | − | |
| 343 | − iser_dbg("Create fr_desc %p page_list %p\n", | |
| 344 | − desc, desc->data_frpl->page_list); | |
| 345 | 363 | |
| 346 | 364 | return 0; |
| 347 | −sig_mr_failure: | |
| 348 | − ib_dereg_mr(desc->pi_ctx->prot_mr); | |
| 349 | −prot_mr_failure: | |
| 350 | − ib_free_fast_reg_page_list(desc->pi_ctx->prot_frpl); | |
| 351 | −prot_frpl_failure: | |
| 352 | − kfree(desc->pi_ctx); | |
| 353 | 365 | pi_ctx_alloc_failure: |
| 354 | 366 | ib_dereg_mr(desc->data_mr); |
| 355 | 367 | fast_reg_mr_failure: |
| @@ -416,12 +428,8 @@ void iser_free_fastreg_pool(struct ib_conn *ib_conn) · 60 unmodified lines | ||
| 416 | 428 | list_del(&desc->list); |
| 417 | 429 | ib_free_fast_reg_page_list(desc->data_frpl); |
| 418 | 430 | ib_dereg_mr(desc->data_mr); |
| 419 | − if (desc->pi_ctx) { | |
| 420 | − ib_free_fast_reg_page_list(desc->pi_ctx->prot_frpl); | |
| 421 | − ib_dereg_mr(desc->pi_ctx->prot_mr); | |
| 422 | − ib_destroy_mr(desc->pi_ctx->sig_mr); | |
| 423 | − kfree(desc->pi_ctx); | |
| 424 | − } | |
| 431 | + if (desc->pi_ctx) | |
| 432 | + iser_free_pi_ctx(desc->pi_ctx); | |
| 425 | 433 | kfree(desc); |
| 426 | 434 | ++i; |
| 427 | 435 | } |
| @@ -721,7 +729,7 @@ static void iser_connect_error(struct rdma_cm_id *cma_id) · 293 unmodified lines | ||
| 721 | 729 | struct iser_conn *iser_conn; |
| 722 | 730 | |
| 723 | 731 | iser_conn = (struct iser_conn *)cma_id->context; |
| 724 | − iser_conn->state = ISER_CONN_DOWN; | |
| 732 | + iser_conn->state = ISER_CONN_TERMINATING; | |
| 725 | 733 | } |
| 726 | 734 | |
| 727 | 735 | /** |
| @@ -992,93 +1000,6 @@ connect_failure: · 264 unmodified lines | ||
| 992 | 1000 | return err; |
| 993 | 1001 | } |
| 994 | 1002 | |
| 995 | −/** | |
| 996 | − * iser_reg_page_vec - Register physical memory | |
| 997 | − * | |
| 998 | − * returns: 0 on success, errno code on failure | |
| 999 | − */ | |
| 1000 | −int iser_reg_page_vec(struct ib_conn *ib_conn, | |
| 1001 | − struct iser_page_vec *page_vec, | |
| 1002 | − struct iser_mem_reg *mem_reg) | |
| 1003 | −{ | |
| 1004 | − struct ib_pool_fmr *mem; | |
| 1005 | − u64 io_addr; | |
| 1006 | − u64 *page_list; | |
| 1007 | − int status; | |
| 1008 | − | |
| 1009 | − page_list = page_vec->pages; | |
| 1010 | − io_addr = page_list[0]; | |
| 1011 | − | |
| 1012 | − mem = ib_fmr_pool_map_phys(ib_conn->fmr.pool, | |
| 1013 | − page_list, | |
| 1014 | − page_vec->length, | |
| 1015 | − io_addr); | |
| 1016 | − | |
| 1017 | − if (IS_ERR(mem)) { | |
| 1018 | − status = (int)PTR_ERR(mem); | |
| 1019 | − iser_err("ib_fmr_pool_map_phys failed: %d\n", status); | |
| 1020 | − return status; | |
| 1021 | − } | |
| 1022 | − | |
| 1023 | − mem_reg->lkey = mem->fmr->lkey; | |
| 1024 | − mem_reg->rkey = mem->fmr->rkey; | |
| 1025 | − mem_reg->len = page_vec->length * SIZE_4K; | |
| 1026 | − mem_reg->va = io_addr; | |
| 1027 | − mem_reg->mem_h = (void *)mem; | |
| 1028 | − | |
| 1029 | − mem_reg->va += page_vec->offset; | |
| 1030 | − mem_reg->len = page_vec->data_size; | |
| 1031 | − | |
| 1032 | − iser_dbg("PHYSICAL Mem.register, [PHYS p_array: 0x%p, sz: %d, " | |
| 1033 | − "entry[0]: (0x%08lx,%ld)] -> " | |
| 1034 | − "[lkey: 0x%08X mem_h: 0x%p va: 0x%08lX sz: %ld]\n", | |
| 1035 | − page_vec, page_vec->length, | |
| 1036 | − (unsigned long)page_vec->pages[0], | |
| 1037 | − (unsigned long)page_vec->data_size, | |
| 1038 | − (unsigned int)mem_reg->lkey, mem_reg->mem_h, | |
| 1039 | − (unsigned long)mem_reg->va, (unsigned long)mem_reg->len); | |
| 1040 | − return 0; | |
| 1041 | −} | |
| 1042 | − | |
| 1043 | −/** | |
| 1044 | − * Unregister (previosuly registered using FMR) memory. | |
| 1045 | − * If memory is non-FMR does nothing. | |
| 1046 | − */ | |
| 1047 | −void iser_unreg_mem_fmr(struct iscsi_iser_task *iser_task, | |
| 1048 | − enum iser_data_dir cmd_dir) | |
| 1049 | −{ | |
| 1050 | − struct iser_mem_reg *reg = &iser_task->rdma_regd[cmd_dir].reg; | |
| 1051 | − int ret; | |
| 1052 | − | |
| 1053 | − if (!reg->mem_h) | |
| 1054 | − return; | |
| 1055 | − | |
| 1056 | − iser_dbg("PHYSICAL Mem.Unregister mem_h %p\n",reg->mem_h); | |
| 1057 | − | |
| 1058 | − ret = ib_fmr_pool_unmap((struct ib_pool_fmr *)reg->mem_h); | |
| 1059 | − if (ret) | |
| 1060 | − iser_err("ib_fmr_pool_unmap failed %d\n", ret); | |
| 1061 | − | |
| 1062 | − reg->mem_h = NULL; | |
| 1063 | −} | |
| 1064 | − | |
| 1065 | −void iser_unreg_mem_fastreg(struct iscsi_iser_task *iser_task, | |
| 1066 | − enum iser_data_dir cmd_dir) | |
| 1067 | −{ | |
| 1068 | − struct iser_mem_reg *reg = &iser_task->rdma_regd[cmd_dir].reg; | |
| 1069 | − struct iser_conn *iser_conn = iser_task->iser_conn; | |
| 1070 | − struct ib_conn *ib_conn = &iser_conn->ib_conn; | |
| 1071 | − struct fast_reg_descriptor *desc = reg->mem_h; | |
| 1072 | − | |
| 1073 | − if (!desc) | |
| 1074 | − return; | |
| 1075 | − | |
| 1076 | − reg->mem_h = NULL; | |
| 1077 | − spin_lock_bh(&ib_conn->lock); | |
| 1078 | − list_add_tail(&desc->list, &ib_conn->fastreg.pool); | |
| 1079 | − spin_unlock_bh(&ib_conn->lock); | |
| 1080 | −} | |
| 1081 | − | |
| 1082 | 1003 | int iser_post_recvl(struct iser_conn *iser_conn) |
| 1083 | 1004 | { |
| 1084 | 1005 | struct ib_recv_wr rx_wr, *rx_wr_failed; |
| @@ -1210,6 +1131,9 @@ iser_handle_comp_error(struct ib_conn *ib_conn, · 125 unmodified lines | ||
| 1210 | 1131 | iscsi_conn_failure(iser_conn->iscsi_conn, |
| 1211 | 1132 | ISCSI_ERR_CONN_FAILED); |
| 1212 | 1133 | |
| 1134 | + if (wc->wr_id == ISER_FASTREG_LI_WRID) | |
| 1135 | + return; | |
| 1136 | + | |
| 1213 | 1137 | if (is_iser_tx_desc(iser_conn, wr_id)) { |
| 1214 | 1138 | struct iser_tx_desc *desc = wr_id; |
| 1215 | 1139 | |
| @@ -1254,13 +1178,11 @@ static void iser_handle_wc(struct ib_wc *wc) · 38 unmodified lines | ||
| 1254 | 1178 | else |
| 1255 | 1179 | iser_dbg("flush error: wr id %llx\n", wc->wr_id); |
| 1256 | 1180 | |
| 1257 | − if (wc->wr_id != ISER_FASTREG_LI_WRID && | |
| 1258 | − wc->wr_id != ISER_BEACON_WRID) | |
| 1259 | − iser_handle_comp_error(ib_conn, wc); | |
| 1260 | − | |
| 1261 | − /* complete in case all flush errors were consumed */ | |
| 1262 | 1181 | if (wc->wr_id == ISER_BEACON_WRID) |
| 1182 | + /* all flush errors were consumed */ | |
| 1263 | 1183 | complete(&ib_conn->flush_comp); |
| 1184 | + else | |
| 1185 | + iser_handle_comp_error(ib_conn, wc); | |
| 1264 | 1186 | } |
| 1265 | 1187 | } |
| 1266 | 1188 | |
| @@ -1306,7 +1228,7 @@ static void iser_cq_callback(struct ib_cq *cq, void *cq_context) · 39 unmodified lines | ||
| 1306 | 1228 | u8 iser_check_task_pi_status(struct iscsi_iser_task *iser_task, |
| 1307 | 1229 | enum iser_data_dir cmd_dir, sector_t *sector) |
| 1308 | 1230 | { |
| 1309 | − struct iser_mem_reg *reg = &iser_task->rdma_regd[cmd_dir].reg; | |
| 1231 | + struct iser_mem_reg *reg = &iser_task->rdma_reg[cmd_dir]; | |
| 1310 | 1232 | struct fast_reg_descriptor *desc = reg->mem_h; |
| 1311 | 1233 | unsigned long sector_size = iser_task->sc->device->sector_size; |
| 1312 | 1234 | struct ib_mr_status mr_status; |
| @@ -40,6 +40,7 @@ · 39 unmodified lines | ||
| 40 | 40 | #include <linux/parser.h> |
| 41 | 41 | #include <linux/random.h> |
| 42 | 42 | #include <linux/jiffies.h> |
| 43 | +#include <rdma/ib_cache.h> | |
| 43 | 44 | |
| 44 | 45 | #include <linux/atomic.h> |
| 45 | 46 | |
| @@ -265,10 +266,10 @@ static int srp_init_qp(struct srp_target_port *target, · 219 unmodified lines | ||
| 265 | 266 | if (!attr) |
| 266 | 267 | return -ENOMEM; |
| 267 | 268 | |
| 268 | − ret = ib_find_pkey(target->srp_host->srp_dev->dev, | |
| 269 | − target->srp_host->port, | |
| 270 | − be16_to_cpu(target->pkey), | |
| 271 | − &attr->pkey_index); | |
| 269 | + ret = ib_find_cached_pkey(target->srp_host->srp_dev->dev, | |
| 270 | + target->srp_host->port, | |
| 271 | + be16_to_cpu(target->pkey), | |
| 272 | + &attr->pkey_index); | |
| 272 | 273 | if (ret) |
| 273 | 274 | goto out; |
| 274 | 275 | |
| @@ -207,7 +207,7 @@ static void srpt_event_handler(struct ib_event_handler *handler, · 206 unmodified lines | ||
| 207 | 207 | } |
| 208 | 208 | break; |
| 209 | 209 | default: |
| 210 | − printk(KERN_ERR "received unrecognized IB event %d\n", | |
| 210 | + pr_err("received unrecognized IB event %d\n", | |
| 211 | 211 | event->event); |
| 212 | 212 | break; |
| 213 | 213 | } |
| @@ -218,7 +218,7 @@ static void srpt_event_handler(struct ib_event_handler *handler, · 4 unmodified lines | ||
| 218 | 218 | */ |
| 219 | 219 | static void srpt_srq_event(struct ib_event *event, void *ctx) |
| 220 | 220 | { |
| 221 | − printk(KERN_INFO "SRQ event %d\n", event->event); | |
| 221 | + pr_info("SRQ event %d\n", event->event); | |
| 222 | 222 | } |
| 223 | 223 | |
| 224 | 224 | /** |
| @@ -242,8 +242,7 @@ static void srpt_qp_event(struct ib_event *event, struct srpt_rdma_ch *ch) · 17 unmodified lines | ||
| 242 | 242 | ch->sess_name, srpt_get_ch_state(ch)); |
| 243 | 243 | break; |
| 244 | 244 | default: |
| 245 | − printk(KERN_ERR "received unrecognized IB QP event %d\n", | |
| 246 | − event->event); | |
| 245 | + pr_err("received unrecognized IB QP event %d\n", event->event); | |
| 247 | 246 | break; |
| 248 | 247 | } |
| 249 | 248 | } |
| @@ -602,7 +601,7 @@ static void srpt_unregister_mad_agent(struct srpt_device *sdev) · 352 unmodified lines | ||
| 602 | 601 | sport = &sdev->port[i - 1]; |
| 603 | 602 | WARN_ON(sport->port != i); |
| 604 | 603 | if (ib_modify_port(sdev->device, i, 0, &port_modify) < 0) |
| 605 | − printk(KERN_ERR "disabling MAD processing failed.\n"); | |
| 604 | + pr_err("disabling MAD processing failed.\n"); | |
| 606 | 605 | if (sport->mad_agent) { |
| 607 | 606 | ib_unregister_mad_agent(sport->mad_agent); |
| 608 | 607 | sport->mad_agent = NULL; |
| @@ -810,7 +809,7 @@ static int srpt_post_send(struct srpt_rdma_ch *ch, · 201 unmodified lines | ||
| 810 | 809 | |
| 811 | 810 | ret = -ENOMEM; |
| 812 | 811 | if (unlikely(atomic_dec_return(&ch->sq_wr_avail) < 0)) { |
| 813 | − printk(KERN_WARNING "IB send queue full (needed 1)\n"); | |
| 812 | + pr_warn("IB send queue full (needed 1)\n"); | |
| 814 | 813 | goto out; |
| 815 | 814 | } |
| 816 | 815 | |
| @@ -912,7 +911,7 @@ static int srpt_get_desc_tbl(struct srpt_send_ioctx *ioctx, · 95 unmodified lines | ||
| 912 | 911 | |
| 913 | 912 | if (ioctx->n_rbuf > |
| 914 | 913 | (srp_cmd->data_out_desc_cnt + srp_cmd->data_in_desc_cnt)) { |
| 915 | − printk(KERN_ERR "received unsupported SRP_CMD request" | |
| 914 | + pr_err("received unsupported SRP_CMD request" | |
| 916 | 915 | " type (%u out + %u in != %u / %zu)\n", |
| 917 | 916 | srp_cmd->data_out_desc_cnt, |
| 918 | 917 | srp_cmd->data_in_desc_cnt, |
| @@ -1432,7 +1431,7 @@ static void srpt_handle_send_comp(struct srpt_rdma_ch *ch, · 513 unmodified lines | ||
| 1432 | 1431 | srpt_unmap_sg_to_ib_sge(ch, ioctx); |
| 1433 | 1432 | transport_generic_free_cmd(&ioctx->cmd, 0); |
| 1434 | 1433 | } else { |
| 1435 | − printk(KERN_ERR "IB completion has been received too late for" | |
| 1434 | + pr_err("IB completion has been received too late for" | |
| 1436 | 1435 | " wr_id = %u.\n", ioctx->ioctx.index); |
| 1437 | 1436 | } |
| 1438 | 1437 | } |
| @@ -1457,7 +1456,7 @@ static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch, · 18 unmodified lines | ||
| 1457 | 1456 | SRPT_STATE_DATA_IN)) |
| 1458 | 1457 | target_execute_cmd(&ioctx->cmd); |
| 1459 | 1458 | else |
| 1460 | − printk(KERN_ERR "%s[%d]: wrong state = %d\n", __func__, | |
| 1459 | + pr_err("%s[%d]: wrong state = %d\n", __func__, | |
| 1461 | 1460 | __LINE__, srpt_get_cmd_state(ioctx)); |
| 1462 | 1461 | } else if (opcode == SRPT_RDMA_ABORT) { |
| 1463 | 1462 | ioctx->rdma_aborted = true; |
| @@ -1481,7 +1480,7 @@ static void srpt_handle_rdma_err_comp(struct srpt_rdma_ch *ch, · 17 unmodified lines | ||
| 1481 | 1480 | switch (opcode) { |
| 1482 | 1481 | case SRPT_RDMA_READ_LAST: |
| 1483 | 1482 | if (ioctx->n_rdma <= 0) { |
| 1484 | − printk(KERN_ERR "Received invalid RDMA read" | |
| 1483 | + pr_err("Received invalid RDMA read" | |
| 1485 | 1484 | " error completion with idx %d\n", |
| 1486 | 1485 | ioctx->ioctx.index); |
| 1487 | 1486 | break; |
| @@ -1490,14 +1489,13 @@ static void srpt_handle_rdma_err_comp(struct srpt_rdma_ch *ch, · 2 unmodified lines | ||
| 1490 | 1489 | if (state == SRPT_STATE_NEED_DATA) |
| 1491 | 1490 | srpt_abort_cmd(ioctx); |
| 1492 | 1491 | else |
| 1493 | − printk(KERN_ERR "%s[%d]: wrong state = %d\n", | |
| 1492 | + pr_err("%s[%d]: wrong state = %d\n", | |
| 1494 | 1493 | __func__, __LINE__, state); |
| 1495 | 1494 | break; |
| 1496 | 1495 | case SRPT_RDMA_WRITE_LAST: |
| 1497 | 1496 | break; |
| 1498 | 1497 | default: |
| 1499 | − printk(KERN_ERR "%s[%d]: opcode = %u\n", __func__, | |
| 1500 | − __LINE__, opcode); | |
| 1498 | + pr_err("%s[%d]: opcode = %u\n", __func__, __LINE__, opcode); | |
| 1501 | 1499 | break; |
| 1502 | 1500 | } |
| 1503 | 1501 | } |
| @@ -1549,8 +1547,8 @@ static int srpt_build_cmd_rsp(struct srpt_rdma_ch *ch, · 45 unmodified lines | ||
| 1549 | 1547 | BUILD_BUG_ON(MIN_MAX_RSP_SIZE <= sizeof(*srp_rsp)); |
| 1550 | 1548 | max_sense_len = ch->max_ti_iu_len - sizeof(*srp_rsp); |
| 1551 | 1549 | if (sense_data_len > max_sense_len) { |
| 1552 | − printk(KERN_WARNING "truncated sense data from %d to %d" | |
| 1553 | − " bytes\n", sense_data_len, max_sense_len); | |
| 1550 | + pr_warn("truncated sense data from %d to %d" | |
| 1551 | + " bytes\n", sense_data_len, max_sense_len); | |
| 1554 | 1552 | sense_data_len = max_sense_len; |
| 1555 | 1553 | } |
| 1556 | 1554 | |
| @@ -1628,8 +1626,8 @@ static uint64_t srpt_unpack_lun(const uint8_t *lun, int len) · 71 unmodified lines | ||
| 1628 | 1626 | int addressing_method; |
| 1629 | 1627 | |
| 1630 | 1628 | if (unlikely(len < 2)) { |
| 1631 | − printk(KERN_ERR "Illegal LUN length %d, expected 2 bytes or " | |
| 1632 | − "more", len); | |
| 1629 | + pr_err("Illegal LUN length %d, expected 2 bytes or more\n", | |
| 1630 | + len); | |
| 1633 | 1631 | goto out; |
| 1634 | 1632 | } |
| 1635 | 1633 | |
| @@ -1663,7 +1661,7 @@ static uint64_t srpt_unpack_lun(const uint8_t *lun, int len) · 27 unmodified lines | ||
| 1663 | 1661 | |
| 1664 | 1662 | case SCSI_LUN_ADDR_METHOD_EXTENDED_LUN: |
| 1665 | 1663 | default: |
| 1666 | − printk(KERN_ERR "Unimplemented LUN addressing method %u", | |
| 1664 | + pr_err("Unimplemented LUN addressing method %u\n", | |
| 1667 | 1665 | addressing_method); |
| 1668 | 1666 | break; |
| 1669 | 1667 | } |
| @@ -1672,8 +1670,7 @@ out: · 2 unmodified lines | ||
| 1672 | 1670 | return res; |
| 1673 | 1671 | |
| 1674 | 1672 | out_err: |
| 1675 | − printk(KERN_ERR "Support for multi-level LUNs has not yet been" | |
| 1676 | − " implemented"); | |
| 1673 | + pr_err("Support for multi-level LUNs has not yet been implemented\n"); | |
| 1677 | 1674 | goto out; |
| 1678 | 1675 | } |
| 1679 | 1676 | |
| @@ -1723,7 +1720,7 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, · 43 unmodified lines | ||
| 1723 | 1720 | } |
| 1724 | 1721 | |
| 1725 | 1722 | if (srpt_get_desc_tbl(send_ioctx, srp_cmd, &dir, &data_len)) { |
| 1726 | − printk(KERN_ERR "0x%llx: parsing SRP descriptor table failed.\n", | |
| 1723 | + pr_err("0x%llx: parsing SRP descriptor table failed.\n", | |
| 1727 | 1724 | srp_cmd->tag); |
| 1728 | 1725 | ret = TCM_INVALID_CDB_FIELD; |
| 1729 | 1726 | goto send_sense; |
| @@ -1912,7 +1909,7 @@ static void srpt_handle_new_iu(struct srpt_rdma_ch *ch, · 182 unmodified lines | ||
| 1912 | 1909 | srpt_handle_tsk_mgmt(ch, recv_ioctx, send_ioctx); |
| 1913 | 1910 | break; |
| 1914 | 1911 | case SRP_I_LOGOUT: |
| 1915 | − printk(KERN_ERR "Not yet implemented: SRP_I_LOGOUT\n"); | |
| 1912 | + pr_err("Not yet implemented: SRP_I_LOGOUT\n"); | |
| 1916 | 1913 | break; |
| 1917 | 1914 | case SRP_CRED_RSP: |
| 1918 | 1915 | pr_debug("received SRP_CRED_RSP\n"); |
| @@ -1921,10 +1918,10 @@ static void srpt_handle_new_iu(struct srpt_rdma_ch *ch, · 2 unmodified lines | ||
| 1921 | 1918 | pr_debug("received SRP_AER_RSP\n"); |
| 1922 | 1919 | break; |
| 1923 | 1920 | case SRP_RSP: |
| 1924 | − printk(KERN_ERR "Received SRP_RSP\n"); | |
| 1921 | + pr_err("Received SRP_RSP\n"); | |
| 1925 | 1922 | break; |
| 1926 | 1923 | default: |
| 1927 | − printk(KERN_ERR "received IU with unknown opcode 0x%x\n", | |
| 1924 | + pr_err("received IU with unknown opcode 0x%x\n", | |
| 1928 | 1925 | srp_cmd->opcode); |
| 1929 | 1926 | break; |
| 1930 | 1927 | } |
| @@ -1948,12 +1945,12 @@ static void srpt_process_rcv_completion(struct ib_cq *cq, · 17 unmodified lines | ||
| 1948 | 1945 | |
| 1949 | 1946 | req_lim = atomic_dec_return(&ch->req_lim); |
| 1950 | 1947 | if (unlikely(req_lim < 0)) |
| 1951 | − printk(KERN_ERR "req_lim = %d < 0\n", req_lim); | |
| 1948 | + pr_err("req_lim = %d < 0\n", req_lim); | |
| 1952 | 1949 | ioctx = sdev->ioctx_ring[index]; |
| 1953 | 1950 | srpt_handle_new_iu(ch, ioctx, NULL); |
| 1954 | 1951 | } else { |
| 1955 | − printk(KERN_INFO "receiving failed for idx %u with status %d\n", | |
| 1956 | − index, wc->status); | |
| 1952 | + pr_info("receiving failed for idx %u with status %d\n", | |
| 1953 | + index, wc->status); | |
| 1957 | 1954 | } |
| 1958 | 1955 | } |
| 1959 | 1956 | |
| @@ -1993,12 +1990,12 @@ static void srpt_process_send_completion(struct ib_cq *cq, · 33 unmodified lines | ||
| 1993 | 1990 | } |
| 1994 | 1991 | } else { |
| 1995 | 1992 | if (opcode == SRPT_SEND) { |
| 1996 | − printk(KERN_INFO "sending response for idx %u failed" | |
| 1997 | − " with status %d\n", index, wc->status); | |
| 1993 | + pr_info("sending response for idx %u failed" | |
| 1994 | + " with status %d\n", index, wc->status); | |
| 1998 | 1995 | srpt_handle_send_err_comp(ch, wc->wr_id); |
| 1999 | 1996 | } else if (opcode != SRPT_RDMA_MID) { |
| 2000 | − printk(KERN_INFO "RDMA t %d for idx %u failed with" | |
| 2001 | − " status %d", opcode, index, wc->status); | |
| 1997 | + pr_info("RDMA t %d for idx %u failed with" | |
| 1998 | + " status %d\n", opcode, index, wc->status); | |
| 2002 | 1999 | srpt_handle_rdma_err_comp(ch, send_ioctx, opcode); |
| 2003 | 2000 | } |
| 2004 | 2001 | } |
| @@ -2062,15 +2059,15 @@ static int srpt_compl_thread(void *arg) · 57 unmodified lines | ||
| 2062 | 2059 | |
| 2063 | 2060 | ch = arg; |
| 2064 | 2061 | BUG_ON(!ch); |
| 2065 | − printk(KERN_INFO "Session %s: kernel thread %s (PID %d) started\n", | |
| 2066 | − ch->sess_name, ch->thread->comm, current->pid); | |
| 2062 | + pr_info("Session %s: kernel thread %s (PID %d) started\n", | |
| 2063 | + ch->sess_name, ch->thread->comm, current->pid); | |
| 2067 | 2064 | while (!kthread_should_stop()) { |
| 2068 | 2065 | wait_event_interruptible(ch->wait_queue, |
| 2069 | 2066 | (srpt_process_completion(ch->cq, ch), |
| 2070 | 2067 | kthread_should_stop())); |
| 2071 | 2068 | } |
| 2072 | − printk(KERN_INFO "Session %s: kernel thread %s (PID %d) stopped\n", | |
| 2073 | − ch->sess_name, ch->thread->comm, current->pid); | |
| 2069 | + pr_info("Session %s: kernel thread %s (PID %d) stopped\n", | |
| 2070 | + ch->sess_name, ch->thread->comm, current->pid); | |
| 2074 | 2071 | return 0; |
| 2075 | 2072 | } |
| 2076 | 2073 | |
| @@ -2097,7 +2094,7 @@ retry: · 20 unmodified lines | ||
| 2097 | 2094 | ch->rq_size + srp_sq_size, 0); |
| 2098 | 2095 | if (IS_ERR(ch->cq)) { |
| 2099 | 2096 | ret = PTR_ERR(ch->cq); |
| 2100 | − printk(KERN_ERR "failed to create CQ cqe= %d ret= %d\n", | |
| 2097 | + pr_err("failed to create CQ cqe= %d ret= %d\n", | |
| 2101 | 2098 | ch->rq_size + srp_sq_size, ret); |
| 2102 | 2099 | goto out; |
| 2103 | 2100 | } |
| @@ -2123,7 +2120,7 @@ retry: · 19 unmodified lines | ||
| 2123 | 2120 | goto retry; |
| 2124 | 2121 | } |
| 2125 | 2122 | } |
| 2126 | − printk(KERN_ERR "failed to create_qp ret= %d\n", ret); | |
| 2123 | + pr_err("failed to create_qp ret= %d\n", ret); | |
| 2127 | 2124 | goto err_destroy_cq; |
| 2128 | 2125 | } |
| 2129 | 2126 | |
| @@ -2143,7 +2140,7 @@ retry: · 13 unmodified lines | ||
| 2143 | 2140 | |
| 2144 | 2141 | ch->thread = kthread_run(srpt_compl_thread, ch, "ib_srpt_compl"); |
| 2145 | 2142 | if (IS_ERR(ch->thread)) { |
| 2146 | − printk(KERN_ERR "failed to create kernel thread %ld\n", | |
| 2143 | + pr_err("failed to create kernel thread %ld\n", | |
| 2147 | 2144 | PTR_ERR(ch->thread)); |
| 2148 | 2145 | ch->thread = NULL; |
| 2149 | 2146 | goto err_destroy_qp; |
| @@ -2204,7 +2201,7 @@ static void __srpt_close_ch(struct srpt_rdma_ch *ch) · 54 unmodified lines | ||
| 2204 | 2201 | /* fall through */ |
| 2205 | 2202 | case CH_LIVE: |
| 2206 | 2203 | if (ib_send_cm_dreq(ch->cm_id, NULL, 0) < 0) |
| 2207 | − printk(KERN_ERR "sending CM DREQ failed.\n"); | |
| 2204 | + pr_err("sending CM DREQ failed.\n"); | |
| 2208 | 2205 | break; |
| 2209 | 2206 | case CH_DISCONNECTING: |
| 2210 | 2207 | break; |
| @@ -2291,7 +2288,7 @@ static void srpt_drain_channel(struct ib_cm_id *cm_id) · 80 unmodified lines | ||
| 2291 | 2288 | |
| 2292 | 2289 | ret = srpt_ch_qp_err(ch); |
| 2293 | 2290 | if (ret < 0) |
| 2294 | − printk(KERN_ERR "Setting queue pair in error state" | |
| 2291 | + pr_err("Setting queue pair in error state" | |
| 2295 | 2292 | " failed: %d\n", ret); |
| 2296 | 2293 | } |
| 2297 | 2294 | } |
| @@ -2435,17 +2432,17 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, · 137 unmodified lines | ||
| 2435 | 2432 | |
| 2436 | 2433 | it_iu_len = be32_to_cpu(req->req_it_iu_len); |
| 2437 | 2434 | |
| 2438 | − printk(KERN_INFO "Received SRP_LOGIN_REQ with i_port_id 0x%llx:0x%llx," | |
| 2439 | − " t_port_id 0x%llx:0x%llx and it_iu_len %d on port %d" | |
| 2440 | − " (guid=0x%llx:0x%llx)\n", | |
| 2441 | − be64_to_cpu(*(__be64 *)&req->initiator_port_id[0]), | |
| 2442 | − be64_to_cpu(*(__be64 *)&req->initiator_port_id[8]), | |
| 2443 | − be64_to_cpu(*(__be64 *)&req->target_port_id[0]), | |
| 2444 | − be64_to_cpu(*(__be64 *)&req->target_port_id[8]), | |
| 2445 | − it_iu_len, | |
| 2446 | − param->port, | |
| 2447 | − be64_to_cpu(*(__be64 *)&sdev->port[param->port - 1].gid.raw[0]), | |
| 2448 | − be64_to_cpu(*(__be64 *)&sdev->port[param->port - 1].gid.raw[8])); | |
| 2435 | + pr_info("Received SRP_LOGIN_REQ with i_port_id 0x%llx:0x%llx," | |
| 2436 | + " t_port_id 0x%llx:0x%llx and it_iu_len %d on port %d" | |
| 2437 | + " (guid=0x%llx:0x%llx)\n", | |
| 2438 | + be64_to_cpu(*(__be64 *)&req->initiator_port_id[0]), | |
| 2439 | + be64_to_cpu(*(__be64 *)&req->initiator_port_id[8]), | |
| 2440 | + be64_to_cpu(*(__be64 *)&req->target_port_id[0]), | |
| 2441 | + be64_to_cpu(*(__be64 *)&req->target_port_id[8]), | |
| 2442 | + it_iu_len, | |
| 2443 | + param->port, | |
| 2444 | + be64_to_cpu(*(__be64 *)&sdev->port[param->port - 1].gid.raw[0]), | |
| 2445 | + be64_to_cpu(*(__be64 *)&sdev->port[param->port - 1].gid.raw[8])); | |
| 2449 | 2446 | |
| 2450 | 2447 | rsp = kzalloc(sizeof *rsp, GFP_KERNEL); |
| 2451 | 2448 | rej = kzalloc(sizeof *rej, GFP_KERNEL); |
| @@ -2460,7 +2457,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, · 8 unmodified lines | ||
| 2460 | 2457 | rej->reason = __constant_cpu_to_be32( |
| 2461 | 2458 | SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE); |
| 2462 | 2459 | ret = -EINVAL; |
| 2463 | − printk(KERN_ERR "rejected SRP_LOGIN_REQ because its" | |
| 2460 | + pr_err("rejected SRP_LOGIN_REQ because its" | |
| 2464 | 2461 | " length (%d bytes) is out of range (%d .. %d)\n", |
| 2465 | 2462 | it_iu_len, 64, srp_max_req_size); |
| 2466 | 2463 | goto reject; |
| @@ -2470,7 +2467,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, · 3 unmodified lines | ||
| 2470 | 2467 | rej->reason = __constant_cpu_to_be32( |
| 2471 | 2468 | SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); |
| 2472 | 2469 | ret = -EINVAL; |
| 2473 | − printk(KERN_ERR "rejected SRP_LOGIN_REQ because the target port" | |
| 2470 | + pr_err("rejected SRP_LOGIN_REQ because the target port" | |
| 2474 | 2471 | " has not yet been enabled\n"); |
| 2475 | 2472 | goto reject; |
| 2476 | 2473 | } |
| @@ -2516,7 +2513,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, · 39 unmodified lines | ||
| 2516 | 2513 | rej->reason = __constant_cpu_to_be32( |
| 2517 | 2514 | SRP_LOGIN_REJ_UNABLE_ASSOCIATE_CHANNEL); |
| 2518 | 2515 | ret = -ENOMEM; |
| 2519 | − printk(KERN_ERR "rejected SRP_LOGIN_REQ because it" | |
| 2516 | + pr_err("rejected SRP_LOGIN_REQ because it" | |
| 2520 | 2517 | " has an invalid target port identifier.\n"); |
| 2521 | 2518 | goto reject; |
| 2522 | 2519 | } |
| @@ -2525,7 +2522,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, · 2 unmodified lines | ||
| 2525 | 2522 | if (!ch) { |
| 2526 | 2523 | rej->reason = __constant_cpu_to_be32( |
| 2527 | 2524 | SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); |
| 2528 | − printk(KERN_ERR "rejected SRP_LOGIN_REQ because no memory.\n"); | |
| 2525 | + pr_err("rejected SRP_LOGIN_REQ because no memory.\n"); | |
| 2529 | 2526 | ret = -ENOMEM; |
| 2530 | 2527 | goto reject; |
| 2531 | 2528 | } |
| @@ -2562,7 +2559,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, · 30 unmodified lines | ||
| 2562 | 2559 | if (ret) { |
| 2563 | 2560 | rej->reason = __constant_cpu_to_be32( |
| 2564 | 2561 | SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); |
| 2565 | − printk(KERN_ERR "rejected SRP_LOGIN_REQ because creating" | |
| 2562 | + pr_err("rejected SRP_LOGIN_REQ because creating" | |
| 2566 | 2563 | " a new RDMA channel failed.\n"); |
| 2567 | 2564 | goto free_ring; |
| 2568 | 2565 | } |
| @@ -2571,7 +2568,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, · 2 unmodified lines | ||
| 2571 | 2568 | if (ret) { |
| 2572 | 2569 | rej->reason = __constant_cpu_to_be32( |
| 2573 | 2570 | SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); |
| 2574 | − printk(KERN_ERR "rejected SRP_LOGIN_REQ because enabling" | |
| 2571 | + pr_err("rejected SRP_LOGIN_REQ because enabling" | |
| 2575 | 2572 | " RTR failed (error code = %d)\n", ret); |
| 2576 | 2573 | goto destroy_ib; |
| 2577 | 2574 | } |
| @@ -2586,8 +2583,8 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, · 8 unmodified lines | ||
| 2586 | 2583 | |
| 2587 | 2584 | nacl = srpt_lookup_acl(sport, ch->i_port_id); |
| 2588 | 2585 | if (!nacl) { |
| 2589 | − printk(KERN_INFO "Rejected login because no ACL has been" | |
| 2590 | − " configured yet for initiator %s.\n", ch->sess_name); | |
| 2586 | + pr_info("Rejected login because no ACL has been" | |
| 2587 | + " configured yet for initiator %s.\n", ch->sess_name); | |
| 2591 | 2588 | rej->reason = __constant_cpu_to_be32( |
| 2592 | 2589 | SRP_LOGIN_REJ_CHANNEL_LIMIT_REACHED); |
| 2593 | 2590 | goto destroy_ib; |
| @@ -2631,7 +2628,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, · 37 unmodified lines | ||
| 2631 | 2628 | |
| 2632 | 2629 | ret = ib_send_cm_rep(cm_id, rep_param); |
| 2633 | 2630 | if (ret) { |
| 2634 | − printk(KERN_ERR "sending SRP_LOGIN_REQ response failed" | |
| 2631 | + pr_err("sending SRP_LOGIN_REQ response failed" | |
| 2635 | 2632 | " (error code = %d)\n", ret); |
| 2636 | 2633 | goto release_channel; |
| 2637 | 2634 | } |
| @@ -2679,7 +2676,7 @@ out: · 41 unmodified lines | ||
| 2679 | 2676 | |
| 2680 | 2677 | static void srpt_cm_rej_recv(struct ib_cm_id *cm_id) |
| 2681 | 2678 | { |
| 2682 | − printk(KERN_INFO "Received IB REJ for cm_id %p.\n", cm_id); | |
| 2679 | + pr_info("Received IB REJ for cm_id %p.\n", cm_id); | |
| 2683 | 2680 | srpt_drain_channel(cm_id); |
| 2684 | 2681 | } |
| 2685 | 2682 | |
| @@ -2714,13 +2711,13 @@ static void srpt_cm_rtu_recv(struct ib_cm_id *cm_id) · 28 unmodified lines | ||
| 2714 | 2711 | |
| 2715 | 2712 | static void srpt_cm_timewait_exit(struct ib_cm_id *cm_id) |
| 2716 | 2713 | { |
| 2717 | − printk(KERN_INFO "Received IB TimeWait exit for cm_id %p.\n", cm_id); | |
| 2714 | + pr_info("Received IB TimeWait exit for cm_id %p.\n", cm_id); | |
| 2718 | 2715 | srpt_drain_channel(cm_id); |
| 2719 | 2716 | } |
| 2720 | 2717 | |
| 2721 | 2718 | static void srpt_cm_rep_error(struct ib_cm_id *cm_id) |
| 2722 | 2719 | { |
| 2723 | − printk(KERN_INFO "Received IB REP error for cm_id %p.\n", cm_id); | |
| 2720 | + pr_info("Received IB REP error for cm_id %p.\n", cm_id); | |
| 2724 | 2721 | srpt_drain_channel(cm_id); |
| 2725 | 2722 | } |
| 2726 | 2723 | |
| @@ -2755,9 +2752,9 @@ static void srpt_cm_dreq_recv(struct ib_cm_id *cm_id) · 28 unmodified lines | ||
| 2755 | 2752 | |
| 2756 | 2753 | if (send_drep) { |
| 2757 | 2754 | if (ib_send_cm_drep(ch->cm_id, NULL, 0) < 0) |
| 2758 | − printk(KERN_ERR "Sending IB DREP failed.\n"); | |
| 2759 | − printk(KERN_INFO "Received DREQ and sent DREP for session %s.\n", | |
| 2760 | − ch->sess_name); | |
| 2755 | + pr_err("Sending IB DREP failed.\n"); | |
| 2756 | + pr_info("Received DREQ and sent DREP for session %s.\n", | |
| 2757 | + ch->sess_name); | |
| 2761 | 2758 | } |
| 2762 | 2759 | } |
| 2763 | 2760 | |
| @@ -2766,8 +2763,7 @@ static void srpt_cm_dreq_recv(struct ib_cm_id *cm_id) · 2 unmodified lines | ||
| 2766 | 2763 | */ |
| 2767 | 2764 | static void srpt_cm_drep_recv(struct ib_cm_id *cm_id) |
| 2768 | 2765 | { |
| 2769 | − printk(KERN_INFO "Received InfiniBand DREP message for cm_id %p.\n", | |
| 2770 | − cm_id); | |
| 2766 | + pr_info("Received InfiniBand DREP message for cm_id %p.\n", cm_id); | |
| 2771 | 2767 | srpt_drain_channel(cm_id); |
| 2772 | 2768 | } |
| 2773 | 2769 | |
| @@ -2811,14 +2807,13 @@ static int srpt_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event) · 37 unmodified lines | ||
| 2811 | 2807 | srpt_cm_rep_error(cm_id); |
| 2812 | 2808 | break; |
| 2813 | 2809 | case IB_CM_DREQ_ERROR: |
| 2814 | − printk(KERN_INFO "Received IB DREQ ERROR event.\n"); | |
| 2810 | + pr_info("Received IB DREQ ERROR event.\n"); | |
| 2815 | 2811 | break; |
| 2816 | 2812 | case IB_CM_MRA_RECEIVED: |
| 2817 | − printk(KERN_INFO "Received IB MRA event\n"); | |
| 2813 | + pr_info("Received IB MRA event\n"); | |
| 2818 | 2814 | break; |
| 2819 | 2815 | default: |
| 2820 | − printk(KERN_ERR "received unrecognized IB CM event %d\n", | |
| 2821 | − event->event); | |
| 2816 | + pr_err("received unrecognized IB CM event %d\n", event->event); | |
| 2822 | 2817 | break; |
| 2823 | 2818 | } |
| 2824 | 2819 | |
| @@ -2848,8 +2843,8 @@ static int srpt_perform_rdmas(struct srpt_rdma_ch *ch, · 23 unmodified lines | ||
| 2848 | 2843 | ret = -ENOMEM; |
| 2849 | 2844 | sq_wr_avail = atomic_sub_return(n_rdma, &ch->sq_wr_avail); |
| 2850 | 2845 | if (sq_wr_avail < 0) { |
| 2851 | − printk(KERN_WARNING "IB send queue full (needed %d)\n", | |
| 2852 | − n_rdma); | |
| 2846 | + pr_warn("IB send queue full (needed %d)\n", | |
| 2847 | + n_rdma); | |
| 2853 | 2848 | goto out; |
| 2854 | 2849 | } |
| 2855 | 2850 | } |
| @@ -2889,7 +2884,7 @@ static int srpt_perform_rdmas(struct srpt_rdma_ch *ch, · 33 unmodified lines | ||
| 2889 | 2884 | } |
| 2890 | 2885 | |
| 2891 | 2886 | if (ret) |
| 2892 | − printk(KERN_ERR "%s[%d]: ib_post_send() returned %d for %d/%d", | |
| 2887 | + pr_err("%s[%d]: ib_post_send() returned %d for %d/%d\n", | |
| 2893 | 2888 | __func__, __LINE__, ret, i, n_rdma); |
| 2894 | 2889 | if (ret && i > 0) { |
| 2895 | 2890 | wr.num_sge = 0; |
| @@ -2897,12 +2892,12 @@ static int srpt_perform_rdmas(struct srpt_rdma_ch *ch, · 1 unmodified line | ||
| 2897 | 2892 | wr.send_flags = IB_SEND_SIGNALED; |
| 2898 | 2893 | while (ch->state == CH_LIVE && |
| 2899 | 2894 | ib_post_send(ch->qp, &wr, &bad_wr) != 0) { |
| 2900 | − printk(KERN_INFO "Trying to abort failed RDMA transfer [%d]", | |
| 2895 | + pr_info("Trying to abort failed RDMA transfer [%d]\n", | |
| 2901 | 2896 | ioctx->ioctx.index); |
| 2902 | 2897 | msleep(1000); |
| 2903 | 2898 | } |
| 2904 | 2899 | while (ch->state != CH_RELEASING && !ioctx->rdma_aborted) { |
| 2905 | − printk(KERN_INFO "Waiting until RDMA abort finished [%d]", | |
| 2900 | + pr_info("Waiting until RDMA abort finished [%d]\n", | |
| 2906 | 2901 | ioctx->ioctx.index); |
| 2907 | 2902 | msleep(1000); |
| 2908 | 2903 | } |
| @@ -2923,17 +2918,17 @@ static int srpt_xfer_data(struct srpt_rdma_ch *ch, · 14 unmodified lines | ||
| 2923 | 2918 | |
| 2924 | 2919 | ret = srpt_map_sg_to_ib_sge(ch, ioctx); |
| 2925 | 2920 | if (ret) { |
| 2926 | − printk(KERN_ERR "%s[%d] ret=%d\n", __func__, __LINE__, ret); | |
| 2921 | + pr_err("%s[%d] ret=%d\n", __func__, __LINE__, ret); | |
| 2927 | 2922 | goto out; |
| 2928 | 2923 | } |
| 2929 | 2924 | |
| 2930 | 2925 | ret = srpt_perform_rdmas(ch, ioctx); |
| 2931 | 2926 | if (ret) { |
| 2932 | 2927 | if (ret == -EAGAIN || ret == -ENOMEM) |
| 2933 | − printk(KERN_INFO "%s[%d] queue full -- ret=%d\n", | |
| 2934 | − __func__, __LINE__, ret); | |
| 2928 | + pr_info("%s[%d] queue full -- ret=%d\n", | |
| 2929 | + __func__, __LINE__, ret); | |
| 2935 | 2930 | else |
| 2936 | − printk(KERN_ERR "%s[%d] fatal error -- ret=%d\n", | |
| 2931 | + pr_err("%s[%d] fatal error -- ret=%d\n", | |
| 2937 | 2932 | __func__, __LINE__, ret); |
| 2938 | 2933 | goto out_unmap; |
| 2939 | 2934 | } |
| @@ -3058,7 +3053,7 @@ static void srpt_queue_response(struct se_cmd *cmd) · 118 unmodified lines | ||
| 3058 | 3053 | !ioctx->queue_status_only) { |
| 3059 | 3054 | ret = srpt_xfer_data(ch, ioctx); |
| 3060 | 3055 | if (ret) { |
| 3061 | − printk(KERN_ERR "xfer_data failed for tag %llu\n", | |
| 3056 | + pr_err("xfer_data failed for tag %llu\n", | |
| 3062 | 3057 | ioctx->tag); |
| 3063 | 3058 | return; |
| 3064 | 3059 | } |
| @@ -3075,7 +3070,7 @@ static void srpt_queue_response(struct se_cmd *cmd) · 10 unmodified lines | ||
| 3075 | 3070 | } |
| 3076 | 3071 | ret = srpt_post_send(ch, ioctx, resp_len); |
| 3077 | 3072 | if (ret) { |
| 3078 | − printk(KERN_ERR "sending cmd response failed for tag %llu\n", | |
| 3073 | + pr_err("sending cmd response failed for tag %llu\n", | |
| 3079 | 3074 | ioctx->tag); |
| 3080 | 3075 | srpt_unmap_sg_to_ib_sge(ch, ioctx); |
| 3081 | 3076 | srpt_set_cmd_state(ioctx, SRPT_STATE_DONE); |
| @@ -3154,7 +3149,7 @@ static int srpt_release_sdev(struct srpt_device *sdev) · 72 unmodified lines | ||
| 3154 | 3149 | res = wait_event_interruptible(sdev->ch_releaseQ, |
| 3155 | 3150 | srpt_ch_list_empty(sdev)); |
| 3156 | 3151 | if (res) |
| 3157 | − printk(KERN_ERR "%s: interrupted.\n", __func__); | |
| 3152 | + pr_err("%s: interrupted.\n", __func__); | |
| 3158 | 3153 | |
| 3159 | 3154 | return 0; |
| 3160 | 3155 | } |
| @@ -3293,7 +3288,7 @@ static void srpt_add_one(struct ib_device *device) · 132 unmodified lines | ||
| 3293 | 3288 | spin_lock_init(&sport->port_acl_lock); |
| 3294 | 3289 | |
| 3295 | 3290 | if (srpt_refresh_port(sport)) { |
| 3296 | − printk(KERN_ERR "MAD registration failed for %s-%d.\n", | |
| 3291 | + pr_err("MAD registration failed for %s-%d.\n", | |
| 3297 | 3292 | srpt_sdev_name(sdev), i); |
| 3298 | 3293 | goto err_ring; |
| 3299 | 3294 | } |
| @@ -3330,7 +3325,7 @@ free_dev: · 30 unmodified lines | ||
| 3330 | 3325 | kfree(sdev); |
| 3331 | 3326 | err: |
| 3332 | 3327 | sdev = NULL; |
| 3333 | − printk(KERN_INFO "%s(%s) failed.\n", __func__, device->name); | |
| 3328 | + pr_info("%s(%s) failed.\n", __func__, device->name); | |
| 3334 | 3329 | goto out; |
| 3335 | 3330 | } |
| 3336 | 3331 | |
| @@ -3344,8 +3339,7 @@ static void srpt_remove_one(struct ib_device *device) · 7 unmodified lines | ||
| 3344 | 3339 | |
| 3345 | 3340 | sdev = ib_get_client_data(device, &srpt_client); |
| 3346 | 3341 | if (!sdev) { |
| 3347 | − printk(KERN_INFO "%s(%s): nothing to do.\n", __func__, | |
| 3348 | − device->name); | |
| 3342 | + pr_info("%s(%s): nothing to do.\n", __func__, device->name); | |
| 3349 | 3343 | return; |
| 3350 | 3344 | } |
| 3351 | 3345 | |
| @@ -3464,7 +3458,7 @@ static struct se_node_acl *srpt_alloc_fabric_acl(struct se_portal_group *se_tpg) · 112 unmodified lines | ||
| 3464 | 3458 | |
| 3465 | 3459 | nacl = kzalloc(sizeof(struct srpt_node_acl), GFP_KERNEL); |
| 3466 | 3460 | if (!nacl) { |
| 3467 | − printk(KERN_ERR "Unable to allocate struct srpt_node_acl\n"); | |
| 3461 | + pr_err("Unable to allocate struct srpt_node_acl\n"); | |
| 3468 | 3462 | return NULL; |
| 3469 | 3463 | } |
| 3470 | 3464 | |
| @@ -3615,7 +3609,7 @@ static struct se_node_acl *srpt_make_nodeacl(struct se_portal_group *tpg, · 144 unmodified lines | ||
| 3615 | 3609 | u8 i_port_id[16]; |
| 3616 | 3610 | |
| 3617 | 3611 | if (srpt_parse_i_port_id(i_port_id, name) < 0) { |
| 3618 | − printk(KERN_ERR "invalid initiator port ID %s\n", name); | |
| 3612 | + pr_err("invalid initiator port ID %s\n", name); | |
| 3619 | 3613 | ret = -EINVAL; |
| 3620 | 3614 | goto err; |
| 3621 | 3615 | } |
| @@ -3816,12 +3810,12 @@ static ssize_t srpt_tpg_store_enable( · 194 unmodified lines | ||
| 3816 | 3810 | |
| 3817 | 3811 | ret = kstrtoul(page, 0, &tmp); |
| 3818 | 3812 | if (ret < 0) { |
| 3819 | − printk(KERN_ERR "Unable to extract srpt_tpg_store_enable\n"); | |
| 3813 | + pr_err("Unable to extract srpt_tpg_store_enable\n"); | |
| 3820 | 3814 | return -EINVAL; |
| 3821 | 3815 | } |
| 3822 | 3816 | |
| 3823 | 3817 | if ((tmp != 0) && (tmp != 1)) { |
| 3824 | − printk(KERN_ERR "Illegal value for srpt_tpg_store_enable: %lu\n", tmp); | |
| 3818 | + pr_err("Illegal value for srpt_tpg_store_enable: %lu\n", tmp); | |
| 3825 | 3819 | return -EINVAL; |
| 3826 | 3820 | } |
| 3827 | 3821 | if (tmp == 1) |
| @@ -3980,7 +3974,7 @@ static int __init srpt_init_module(void) · 152 unmodified lines | ||
| 3980 | 3974 | |
| 3981 | 3975 | ret = -EINVAL; |
| 3982 | 3976 | if (srp_max_req_size < MIN_MAX_REQ_SIZE) { |
| 3983 | − printk(KERN_ERR "invalid value %d for kernel module parameter" | |
| 3977 | + pr_err("invalid value %d for kernel module parameter" | |
| 3984 | 3978 | " srp_max_req_size -- must be at least %d.\n", |
| 3985 | 3979 | srp_max_req_size, MIN_MAX_REQ_SIZE); |
| 3986 | 3980 | goto out; |
| @@ -3988,7 +3982,7 @@ static int __init srpt_init_module(void) · 1 unmodified line | ||
| 3988 | 3982 | |
| 3989 | 3983 | if (srpt_srq_size < MIN_SRPT_SRQ_SIZE |
| 3990 | 3984 | || srpt_srq_size > MAX_SRPT_SRQ_SIZE) { |
| 3991 | − printk(KERN_ERR "invalid value %d for kernel module parameter" | |
| 3985 | + pr_err("invalid value %d for kernel module parameter" | |
| 3992 | 3986 | " srpt_srq_size -- must be in the range [%d..%d].\n", |
| 3993 | 3987 | srpt_srq_size, MIN_SRPT_SRQ_SIZE, MAX_SRPT_SRQ_SIZE); |
| 3994 | 3988 | goto out; |
| @@ -3996,7 +3990,7 @@ static int __init srpt_init_module(void) · 1 unmodified line | ||
| 3996 | 3990 | |
| 3997 | 3991 | srpt_target = target_fabric_configfs_init(THIS_MODULE, "srpt"); |
| 3998 | 3992 | if (IS_ERR(srpt_target)) { |
| 3999 | − printk(KERN_ERR "couldn't register\n"); | |
| 3993 | + pr_err("couldn't register\n"); | |
| 4000 | 3994 | ret = PTR_ERR(srpt_target); |
| 4001 | 3995 | goto out; |
| 4002 | 3996 | } |
| @@ -4018,13 +4012,13 @@ static int __init srpt_init_module(void) · 15 unmodified lines | ||
| 4018 | 4012 | |
| 4019 | 4013 | ret = target_fabric_configfs_register(srpt_target); |
| 4020 | 4014 | if (ret < 0) { |
| 4021 | − printk(KERN_ERR "couldn't register\n"); | |
| 4015 | + pr_err("couldn't register\n"); | |
| 4022 | 4016 | goto out_free_target; |
| 4023 | 4017 | } |
| 4024 | 4018 | |
| 4025 | 4019 | ret = ib_register_client(&srpt_client); |
| 4026 | 4020 | if (ret) { |
| 4027 | − printk(KERN_ERR "couldn't register IB client\n"); | |
| 4021 | + pr_err("couldn't register IB client\n"); | |
| 4028 | 4022 | goto out_unregister_target; |
| 4029 | 4023 | } |
| 4030 | 4024 | |
| @@ -939,21 +939,34 @@ static int mlx4_MAD_IFC_wrapper(struct mlx4_dev *dev, int slave, · 938 unmodified lines | ||
| 939 | 939 | return err; |
| 940 | 940 | } |
| 941 | 941 | if (smp->attr_id == IB_SMP_ATTR_GUID_INFO) { |
| 942 | − /* compute slave's gid block */ | |
| 943 | − smp->attr_mod = cpu_to_be32(slave / 8); | |
| 944 | − /* execute cmd */ | |
| 945 | − err = mlx4_cmd_box(dev, inbox->dma, outbox->dma, | |
| 946 | − vhcr->in_modifier, opcode_modifier, | |
| 947 | − vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE); | |
| 948 | − if (!err) { | |
| 949 | − /* if needed, move slave gid to index 0 */ | |
| 950 | − if (slave % 8) | |
| 951 | − memcpy(outsmp->data, | |
| 952 | − outsmp->data + (slave % 8) * 8, 8); | |
| 953 | − /* delete all other gids */ | |
| 954 | − memset(outsmp->data + 8, 0, 56); | |
| 942 | + __be64 guid = mlx4_get_admin_guid(dev, slave, | |
| 943 | + port); | |
| 944 | + | |
| 945 | + /* set the PF admin guid to the FW/HW burned | |
| 946 | + * GUID, if it wasn't yet set | |
| 947 | + */ | |
| 948 | + if (slave == 0 && guid == 0) { | |
| 949 | + smp->attr_mod = 0; | |
| 950 | + err = mlx4_cmd_box(dev, | |
| 951 | + inbox->dma, | |
| 952 | + outbox->dma, | |
| 953 | + vhcr->in_modifier, | |
| 954 | + opcode_modifier, | |
| 955 | + vhcr->op, | |
| 956 | + MLX4_CMD_TIME_CLASS_C, | |
| 957 | + MLX4_CMD_NATIVE); | |
| 958 | + if (err) | |
| 959 | + return err; | |
| 960 | + mlx4_set_admin_guid(dev, | |
| 961 | + *(__be64 *)outsmp-> | |
| 962 | + data, slave, port); | |
| 963 | + } else { | |
| 964 | + memcpy(outsmp->data, &guid, 8); | |
| 955 | 965 | } |
| 956 | − return err; | |
| 966 | + | |
| 967 | + /* clean all other gids */ | |
| 968 | + memset(outsmp->data + 8, 0, 56); | |
| 969 | + return 0; | |
| 957 | 970 | } |
| 958 | 971 | if (smp->attr_id == IB_SMP_ATTR_NODE_INFO) { |
| 959 | 972 | err = mlx4_cmd_box(dev, inbox->dma, outbox->dma, |
| @@ -2350,6 +2363,7 @@ int mlx4_multi_func_init(struct mlx4_dev *dev) · 1390 unmodified lines | ||
| 2350 | 2363 | oper_vport->qos_vport = MLX4_VPP_DEFAULT_VPORT; |
| 2351 | 2364 | vf_oper->vport[port].vlan_idx = NO_INDX; |
| 2352 | 2365 | vf_oper->vport[port].mac_idx = NO_INDX; |
| 2366 | + mlx4_set_random_admin_guid(dev, i, port); | |
| 2353 | 2367 | } |
| 2354 | 2368 | spin_lock_init(&s_state->lock); |
| 2355 | 2369 | } |
| @@ -702,6 +702,8 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) · 701 unmodified lines | ||
| 702 | 702 | priv->mfunc.master.slave_state[flr_slave].is_slave_going_down = 1; |
| 703 | 703 | } |
| 704 | 704 | spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags); |
| 705 | + mlx4_dispatch_event(dev, MLX4_DEV_EVENT_SLAVE_SHUTDOWN, | |
| 706 | + flr_slave); | |
| 705 | 707 | queue_work(priv->mfunc.master.comm_wq, |
| 706 | 708 | &priv->mfunc.master.slave_flr_event_work); |
| 707 | 709 | break; |
| @@ -2260,6 +2260,37 @@ void mlx4_counter_free(struct mlx4_dev *dev, u32 idx) · 2259 unmodified lines | ||
| 2260 | 2260 | } |
| 2261 | 2261 | EXPORT_SYMBOL_GPL(mlx4_counter_free); |
| 2262 | 2262 | |
| 2263 | +void mlx4_set_admin_guid(struct mlx4_dev *dev, __be64 guid, int entry, int port) | |
| 2264 | +{ | |
| 2265 | + struct mlx4_priv *priv = mlx4_priv(dev); | |
| 2266 | + | |
| 2267 | + priv->mfunc.master.vf_admin[entry].vport[port].guid = guid; | |
| 2268 | +} | |
| 2269 | +EXPORT_SYMBOL_GPL(mlx4_set_admin_guid); | |
| 2270 | + | |
| 2271 | +__be64 mlx4_get_admin_guid(struct mlx4_dev *dev, int entry, int port) | |
| 2272 | +{ | |
| 2273 | + struct mlx4_priv *priv = mlx4_priv(dev); | |
| 2274 | + | |
| 2275 | + return priv->mfunc.master.vf_admin[entry].vport[port].guid; | |
| 2276 | +} | |
| 2277 | +EXPORT_SYMBOL_GPL(mlx4_get_admin_guid); | |
| 2278 | + | |
| 2279 | +void mlx4_set_random_admin_guid(struct mlx4_dev *dev, int entry, int port) | |
| 2280 | +{ | |
| 2281 | + struct mlx4_priv *priv = mlx4_priv(dev); | |
| 2282 | + __be64 guid; | |
| 2283 | + | |
| 2284 | + /* hw GUID */ | |
| 2285 | + if (entry == 0) | |
| 2286 | + return; | |
| 2287 | + | |
| 2288 | + get_random_bytes((char *)&guid, sizeof(guid)); | |
| 2289 | + guid &= ~(cpu_to_be64(1ULL << 56)); | |
| 2290 | + guid |= cpu_to_be64(1ULL << 57); | |
| 2291 | + priv->mfunc.master.vf_admin[entry].vport[port].guid = guid; | |
| 2292 | +} | |
| 2293 | + | |
| 2263 | 2294 | static int mlx4_setup_hca(struct mlx4_dev *dev) |
| 2264 | 2295 | { |
| 2265 | 2296 | struct mlx4_priv *priv = mlx4_priv(dev); |
| @@ -499,6 +499,7 @@ struct mlx4_vport_state { · 498 unmodified lines | ||
| 499 | 499 | bool spoofchk; |
| 500 | 500 | u32 link_state; |
| 501 | 501 | u8 qos_vport; |
| 502 | + __be64 guid; | |
| 502 | 503 | }; |
| 503 | 504 | |
| 504 | 505 | struct mlx4_vf_admin_state { |
| @@ -211,26 +211,28 @@ static int alloc_4k(struct mlx5_core_dev *dev, u64 *addr) · 210 unmodified lines | ||
| 211 | 211 | return 0; |
| 212 | 212 | } |
| 213 | 213 | |
| 214 | +#define MLX5_U64_4K_PAGE_MASK ((~(u64)0U) << PAGE_SHIFT) | |
| 215 | + | |
| 214 | 216 | static void free_4k(struct mlx5_core_dev *dev, u64 addr) |
| 215 | 217 | { |
| 216 | 218 | struct fw_page *fwp; |
| 217 | 219 | int n; |
| 218 | 220 | |
| 219 | − fwp = find_fw_page(dev, addr & PAGE_MASK); | |
| 221 | + fwp = find_fw_page(dev, addr & MLX5_U64_4K_PAGE_MASK); | |
| 220 | 222 | if (!fwp) { |
| 221 | 223 | mlx5_core_warn(dev, "page not found\n"); |
| 222 | 224 | return; |
| 223 | 225 | } |
| 224 | 226 | |
| 225 | − n = (addr & ~PAGE_MASK) >> MLX5_ADAPTER_PAGE_SHIFT; | |
| 227 | + n = (addr & ~MLX5_U64_4K_PAGE_MASK) >> MLX5_ADAPTER_PAGE_SHIFT; | |
| 226 | 228 | fwp->free_count++; |
| 227 | 229 | set_bit(n, &fwp->bitmask); |
| 228 | 230 | if (fwp->free_count == MLX5_NUM_4K_IN_PAGE) { |
| 229 | 231 | rb_erase(&fwp->rb_node, &dev->priv.page_root); |
| 230 | 232 | if (fwp->free_count != 1) |
| 231 | 233 | list_del(&fwp->list); |
| 232 | − dma_unmap_page(&dev->pdev->dev, addr & PAGE_MASK, PAGE_SIZE, | |
| 233 | − DMA_BIDIRECTIONAL); | |
| 234 | + dma_unmap_page(&dev->pdev->dev, addr & MLX5_U64_4K_PAGE_MASK, | |
| 235 | + PAGE_SIZE, DMA_BIDIRECTIONAL); | |
| 234 | 236 | __free_page(fwp->page); |
| 235 | 237 | kfree(fwp); |
| 236 | 238 | } else if (fwp->free_count == 1) { |
| @@ -1345,6 +1345,10 @@ int mlx4_wol_write(struct mlx4_dev *dev, u64 config, int port); · 1344 unmodified lines | ||
| 1345 | 1345 | int mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx); |
| 1346 | 1346 | void mlx4_counter_free(struct mlx4_dev *dev, u32 idx); |
| 1347 | 1347 | |
| 1348 | +void mlx4_set_admin_guid(struct mlx4_dev *dev, __be64 guid, int entry, | |
| 1349 | + int port); | |
| 1350 | +__be64 mlx4_get_admin_guid(struct mlx4_dev *dev, int entry, int port); | |
| 1351 | +void mlx4_set_random_admin_guid(struct mlx4_dev *dev, int entry, int port); | |
| 1348 | 1352 | int mlx4_flow_attach(struct mlx4_dev *dev, |
| 1349 | 1353 | struct mlx4_net_trans_rule *rule, u64 *reg_id); |
| 1350 | 1354 | int mlx4_flow_detach(struct mlx4_dev *dev, u64 reg_id); |