cxgb3 - bind qsets on multiport adapter

Inform FW about the queue set->interface mapping.

Signed-off-by: Divy Le Ray <divy@chelsio.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index 8044146..7e7ee7a 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -649,6 +649,37 @@
 	t3_write_reg(adapter, A_TP_MTU_PORT_TABLE, mtus);
 }
 
+static void send_pktsched_cmd(struct adapter *adap, int sched, int qidx, int lo,
+			      int hi, int port)
+{
+	struct sk_buff *skb;
+	struct mngt_pktsched_wr *req;
+
+	skb = alloc_skb(sizeof(*req), GFP_KERNEL | __GFP_NOFAIL);
+	req = (struct mngt_pktsched_wr *)skb_put(skb, sizeof(*req));
+	req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_MNGT));
+	req->mngt_opcode = FW_MNGTOPCODE_PKTSCHED_SET;
+	req->sched = sched;
+	req->idx = qidx;
+	req->min = lo;
+	req->max = hi;
+	req->binding = port;
+	t3_mgmt_tx(adap, skb);
+}
+
+static void bind_qsets(struct adapter *adap)
+{
+	int i, j;
+
+	for_each_port(adap, i) {
+		const struct port_info *pi = adap2pinfo(adap, i);
+
+		for (j = 0; j < pi->nqsets; ++j)
+			send_pktsched_cmd(adap, 1, pi->first_qset + j, -1,
+					  -1, i);
+	}
+}
+
 /**
  *	cxgb_up - enable the adapter
  *	@adapter: adapter being enabled
@@ -708,6 +739,11 @@
 
 	t3_sge_start(adap);
 	t3_intr_enable(adap);
+
+	if ((adap->flags & (USING_MSIX | QUEUES_BOUND)) == USING_MSIX)
+		bind_qsets(adap);
+	adap->flags |= QUEUES_BOUND;
+
 out:
 	return err;
 irq_err:
@@ -1830,34 +1866,18 @@
 		break;
 	}
 	case CHELSIO_SET_PKTSCHED:{
-		struct sk_buff *skb;
 		struct ch_pktsched_params p;
-		struct mngt_pktsched_wr *req;
 
-		if (!(adapter->flags & FULL_INIT_DONE))
-			return -EIO;	/* uP must be up and running */
+		if (!capable(CAP_NET_ADMIN))
+				return -EPERM;
+		if (!adapter->open_device_map)
+				return -EAGAIN;	/* uP and SGE must be running */
 		if (copy_from_user(&p, useraddr, sizeof(p)))
-			return -EFAULT;
-		skb = alloc_skb(sizeof(*req), GFP_KERNEL);
-		if (!skb)
-			return -ENOMEM;
-		req =
-			(struct mngt_pktsched_wr *)skb_put(skb,
-							sizeof(*req));
-		req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_MNGT));
-		req->mngt_opcode = FW_MNGTOPCODE_PKTSCHED_SET;
-		req->sched = p.sched;
-		req->idx = p.idx;
-		req->min = p.min;
-		req->max = p.max;
-		req->binding = p.binding;
-		printk(KERN_INFO
-			"pktsched: sched %u idx %u min %u max %u binding %u\n",
-			req->sched, req->idx, req->min, req->max,
-			req->binding);
-		skb->priority = 1;
-		offload_tx(&adapter->tdev, skb);
+				return -EFAULT;
+		send_pktsched_cmd(adapter, p.sched, p.idx, p.min, p.max,
+				  p.binding);
 		break;
+			
 	}
 	default:
 		return -EOPNOTSUPP;