Skip to content

Commit bfa738c

Browse files
committed
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma
Pull rdma fixes from Doug Ledford: "Third set of -rc fixes for 4.13 cycle - small set of miscellanous fixes - a reasonably sizable set of IPoIB fixes that deal with multiple long standing issues" * tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma: IB/hns: checking for IS_ERR() instead of NULL RDMA/mlx5: Fix existence check for extended address vector IB/uverbs: Fix device cleanup RDMA/uverbs: Prevent leak of reserved field IB/core: Fix race condition in resolving IP to MAC IB/ipoib: Notify on modify QP failure only when relevant Revert "IB/core: Allow QP state transition from reset to error" IB/ipoib: Remove double pointer assigning IB/ipoib: Clean error paths in add port IB/ipoib: Add get statistics support to SRIOV VF IB/ipoib: Add multicast packets statistics IB/ipoib: Set IPOIB_NEIGH_TBL_FLUSH after flushed completion initialization IB/ipoib: Prevent setting negative values to max_nonsrq_conn_qp IB/ipoib: Make sure no in-flight joins while leaving that mcast IB/ipoib: Use cancel_delayed_work_sync when needed IB/ipoib: Fix race between light events and interface restart
2 parents b95c29a + 48107c4 commit bfa738c

File tree

13 files changed

+102
-53
lines changed

13 files changed

+102
-53
lines changed

drivers/infiniband/core/addr.c

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ struct addr_req {
6161
void (*callback)(int status, struct sockaddr *src_addr,
6262
struct rdma_dev_addr *addr, void *context);
6363
unsigned long timeout;
64+
struct delayed_work work;
6465
int status;
6566
u32 seq;
6667
};
@@ -295,15 +296,15 @@ int rdma_translate_ip(const struct sockaddr *addr,
295296
}
296297
EXPORT_SYMBOL(rdma_translate_ip);
297298

298-
static void set_timeout(unsigned long time)
299+
static void set_timeout(struct delayed_work *delayed_work, unsigned long time)
299300
{
300301
unsigned long delay;
301302

302303
delay = time - jiffies;
303304
if ((long)delay < 0)
304305
delay = 0;
305306

306-
mod_delayed_work(addr_wq, &work, delay);
307+
mod_delayed_work(addr_wq, delayed_work, delay);
307308
}
308309

309310
static void queue_req(struct addr_req *req)
@@ -318,8 +319,7 @@ static void queue_req(struct addr_req *req)
318319

319320
list_add(&req->list, &temp_req->list);
320321

321-
if (req_list.next == &req->list)
322-
set_timeout(req->timeout);
322+
set_timeout(&req->work, req->timeout);
323323
mutex_unlock(&lock);
324324
}
325325

@@ -574,6 +574,37 @@ static int addr_resolve(struct sockaddr *src_in,
574574
return ret;
575575
}
576576

577+
static void process_one_req(struct work_struct *_work)
578+
{
579+
struct addr_req *req;
580+
struct sockaddr *src_in, *dst_in;
581+
582+
mutex_lock(&lock);
583+
req = container_of(_work, struct addr_req, work.work);
584+
585+
if (req->status == -ENODATA) {
586+
src_in = (struct sockaddr *)&req->src_addr;
587+
dst_in = (struct sockaddr *)&req->dst_addr;
588+
req->status = addr_resolve(src_in, dst_in, req->addr,
589+
true, req->seq);
590+
if (req->status && time_after_eq(jiffies, req->timeout)) {
591+
req->status = -ETIMEDOUT;
592+
} else if (req->status == -ENODATA) {
593+
/* requeue the work for retrying again */
594+
set_timeout(&req->work, req->timeout);
595+
mutex_unlock(&lock);
596+
return;
597+
}
598+
}
599+
list_del(&req->list);
600+
mutex_unlock(&lock);
601+
602+
req->callback(req->status, (struct sockaddr *)&req->src_addr,
603+
req->addr, req->context);
604+
put_client(req->client);
605+
kfree(req);
606+
}
607+
577608
static void process_req(struct work_struct *work)
578609
{
579610
struct addr_req *req, *temp_req;
@@ -591,20 +622,23 @@ static void process_req(struct work_struct *work)
591622
true, req->seq);
592623
if (req->status && time_after_eq(jiffies, req->timeout))
593624
req->status = -ETIMEDOUT;
594-
else if (req->status == -ENODATA)
625+
else if (req->status == -ENODATA) {
626+
set_timeout(&req->work, req->timeout);
595627
continue;
628+
}
596629
}
597630
list_move_tail(&req->list, &done_list);
598631
}
599632

600-
if (!list_empty(&req_list)) {
601-
req = list_entry(req_list.next, struct addr_req, list);
602-
set_timeout(req->timeout);
603-
}
604633
mutex_unlock(&lock);
605634

606635
list_for_each_entry_safe(req, temp_req, &done_list, list) {
607636
list_del(&req->list);
637+
/* It is safe to cancel other work items from this work item
638+
* because at a time there can be only one work item running
639+
* with this single threaded work queue.
640+
*/
641+
cancel_delayed_work(&req->work);
608642
req->callback(req->status, (struct sockaddr *) &req->src_addr,
609643
req->addr, req->context);
610644
put_client(req->client);
@@ -647,6 +681,7 @@ int rdma_resolve_ip(struct rdma_addr_client *client,
647681
req->context = context;
648682
req->client = client;
649683
atomic_inc(&client->refcount);
684+
INIT_DELAYED_WORK(&req->work, process_one_req);
650685
req->seq = (u32)atomic_inc_return(&ib_nl_addr_request_seq);
651686

652687
req->status = addr_resolve(src_in, dst_in, addr, true, req->seq);
@@ -701,7 +736,7 @@ void rdma_addr_cancel(struct rdma_dev_addr *addr)
701736
req->status = -ECANCELED;
702737
req->timeout = jiffies;
703738
list_move(&req->list, &req_list);
704-
set_timeout(req->timeout);
739+
set_timeout(&req->work, req->timeout);
705740
break;
706741
}
707742
}
@@ -807,9 +842,8 @@ static int netevent_callback(struct notifier_block *self, unsigned long event,
807842
if (event == NETEVENT_NEIGH_UPDATE) {
808843
struct neighbour *neigh = ctx;
809844

810-
if (neigh->nud_state & NUD_VALID) {
811-
set_timeout(jiffies);
812-
}
845+
if (neigh->nud_state & NUD_VALID)
846+
set_timeout(&work, jiffies);
813847
}
814848
return 0;
815849
}
@@ -820,7 +854,7 @@ static struct notifier_block nb = {
820854

821855
int addr_init(void)
822856
{
823-
addr_wq = alloc_workqueue("ib_addr", WQ_MEM_RECLAIM, 0);
857+
addr_wq = alloc_ordered_workqueue("ib_addr", WQ_MEM_RECLAIM);
824858
if (!addr_wq)
825859
return -ENOMEM;
826860

drivers/infiniband/core/uverbs_cmd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1153,7 +1153,7 @@ ssize_t ib_uverbs_resize_cq(struct ib_uverbs_file *file,
11531153
int out_len)
11541154
{
11551155
struct ib_uverbs_resize_cq cmd;
1156-
struct ib_uverbs_resize_cq_resp resp;
1156+
struct ib_uverbs_resize_cq_resp resp = {};
11571157
struct ib_udata udata;
11581158
struct ib_cq *cq;
11591159
int ret = -EINVAL;

drivers/infiniband/core/uverbs_main.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ void ib_uverbs_release_file(struct kref *ref)
250250
if (atomic_dec_and_test(&file->device->refcount))
251251
ib_uverbs_comp_dev(file->device);
252252

253+
kobject_put(&file->device->kobj);
253254
kfree(file);
254255
}
255256

@@ -917,7 +918,6 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
917918
static int ib_uverbs_close(struct inode *inode, struct file *filp)
918919
{
919920
struct ib_uverbs_file *file = filp->private_data;
920-
struct ib_uverbs_device *dev = file->device;
921921

922922
mutex_lock(&file->cleanup_mutex);
923923
if (file->ucontext) {
@@ -939,7 +939,6 @@ static int ib_uverbs_close(struct inode *inode, struct file *filp)
939939
ib_uverbs_release_async_event_file);
940940

941941
kref_put(&file->ref, ib_uverbs_release_file);
942-
kobject_put(&dev->kobj);
943942

944943
return 0;
945944
}

drivers/infiniband/core/verbs.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -895,7 +895,6 @@ static const struct {
895895
} qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
896896
[IB_QPS_RESET] = {
897897
[IB_QPS_RESET] = { .valid = 1 },
898-
[IB_QPS_ERR] = { .valid = 1 },
899898
[IB_QPS_INIT] = {
900899
.valid = 1,
901900
.req_param = {

drivers/infiniband/hw/hns/hns_roce_hw_v1.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -733,7 +733,7 @@ static int hns_roce_v1_rsv_lp_qp(struct hns_roce_dev *hr_dev)
733733
continue;
734734

735735
free_mr->mr_free_qp[i] = hns_roce_v1_create_lp_qp(hr_dev, pd);
736-
if (IS_ERR(free_mr->mr_free_qp[i])) {
736+
if (!free_mr->mr_free_qp[i]) {
737737
dev_err(dev, "Create loop qp failed!\n");
738738
goto create_lp_qp_failed;
739739
}

drivers/infiniband/hw/mlx5/odp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -939,7 +939,7 @@ static int mlx5_ib_mr_initiator_pfault_handler(
939939

940940
if (qp->ibqp.qp_type != IB_QPT_RC) {
941941
av = *wqe;
942-
if (av->dqp_dct & be32_to_cpu(MLX5_WQE_AV_EXT))
942+
if (av->dqp_dct & cpu_to_be32(MLX5_EXTENDED_UD_AV))
943943
*wqe += sizeof(struct mlx5_av);
944944
else
945945
*wqe += sizeof(struct mlx5_base_av);

drivers/infiniband/ulp/ipoib/ipoib.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@ struct ipoib_dev_priv {
336336
unsigned long flags;
337337

338338
struct rw_semaphore vlan_rwsem;
339+
struct mutex mcast_mutex;
339340

340341
struct rb_root path_tree;
341342
struct list_head path_list;

drivers/infiniband/ulp/ipoib/ipoib_cm.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,6 @@ static int ipoib_cm_rx_handler(struct ib_cm_id *cm_id,
511511
case IB_CM_REQ_RECEIVED:
512512
return ipoib_cm_req_handler(cm_id, event);
513513
case IB_CM_DREQ_RECEIVED:
514-
p = cm_id->context;
515514
ib_send_cm_drep(cm_id, NULL, 0);
516515
/* Fall through */
517516
case IB_CM_REJ_RECEIVED:

drivers/infiniband/ulp/ipoib/ipoib_ethtool.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ static const struct ipoib_stats ipoib_gstrings_stats[] = {
5252
IPOIB_NETDEV_STAT(tx_bytes),
5353
IPOIB_NETDEV_STAT(tx_errors),
5454
IPOIB_NETDEV_STAT(rx_dropped),
55-
IPOIB_NETDEV_STAT(tx_dropped)
55+
IPOIB_NETDEV_STAT(tx_dropped),
56+
IPOIB_NETDEV_STAT(multicast),
5657
};
5758

5859
#define IPOIB_GLOBAL_STATS_LEN ARRAY_SIZE(ipoib_gstrings_stats)

drivers/infiniband/ulp/ipoib/ipoib_ib.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,8 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
256256

257257
++dev->stats.rx_packets;
258258
dev->stats.rx_bytes += skb->len;
259+
if (skb->pkt_type == PACKET_MULTICAST)
260+
dev->stats.multicast++;
259261

260262
skb->dev = dev;
261263
if ((dev->features & NETIF_F_RXCSUM) &&
@@ -709,6 +711,27 @@ static int recvs_pending(struct net_device *dev)
709711
return pending;
710712
}
711713

714+
static void check_qp_movement_and_print(struct ipoib_dev_priv *priv,
715+
struct ib_qp *qp,
716+
enum ib_qp_state new_state)
717+
{
718+
struct ib_qp_attr qp_attr;
719+
struct ib_qp_init_attr query_init_attr;
720+
int ret;
721+
722+
ret = ib_query_qp(qp, &qp_attr, IB_QP_STATE, &query_init_attr);
723+
if (ret) {
724+
ipoib_warn(priv, "%s: Failed to query QP\n", __func__);
725+
return;
726+
}
727+
/* print according to the new-state and the previous state.*/
728+
if (new_state == IB_QPS_ERR && qp_attr.qp_state == IB_QPS_RESET)
729+
ipoib_dbg(priv, "Failed modify QP, IB_QPS_RESET to IB_QPS_ERR, acceptable\n");
730+
else
731+
ipoib_warn(priv, "Failed to modify QP to state: %d from state: %d\n",
732+
new_state, qp_attr.qp_state);
733+
}
734+
712735
int ipoib_ib_dev_stop_default(struct net_device *dev)
713736
{
714737
struct ipoib_dev_priv *priv = ipoib_priv(dev);
@@ -728,7 +751,7 @@ int ipoib_ib_dev_stop_default(struct net_device *dev)
728751
*/
729752
qp_attr.qp_state = IB_QPS_ERR;
730753
if (ib_modify_qp(priv->qp, &qp_attr, IB_QP_STATE))
731-
ipoib_warn(priv, "Failed to modify QP to ERROR state\n");
754+
check_qp_movement_and_print(priv, priv->qp, IB_QPS_ERR);
732755

733756
/* Wait for all sends and receives to complete */
734757
begin = jiffies;

0 commit comments

Comments
 (0)