greybus: es2: get cport count from apb1 usb device

Use the control request REQUEST_CPORT_COUNT in order to get the number of
CPorts supported by the UniPro IP.

Signed-off-by: Fabien Parent <fparent@baylibre.com>
Signed-off-by: Johan Hovold <johan@hovoldconsulting.com>
diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c
index 909ca6a..13605b8 100644
--- a/drivers/staging/greybus/es2.c
+++ b/drivers/staging/greybus/es2.c
@@ -33,9 +33,6 @@
 static struct task_struct *apb1_log_task;
 static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE);
 
-/* Number of cport present on USB bridge */
-#define CPORT_COUNT		44
-
 /* Number of bulk in and bulk out couple */
 #define NUM_BULKS		7
 
@@ -60,6 +57,9 @@
 /* vendor request to map a cport to bulk in and bulk out endpoints */
 #define REQUEST_EP_MAPPING	0x03
 
+/* vendor request to get the number of cports available */
+#define REQUEST_CPORT_COUNT	0x04
+
 /*
  * @endpoint: bulk in endpoint for CPort data
  * @urb: array of urbs for the CPort in messages
@@ -636,6 +636,39 @@
 	.write	= apb1_log_enable_write,
 };
 
+static int apb1_get_cport_count(struct usb_device *udev)
+{
+	int retval;
+	__le16 *cport_count;
+
+	cport_count = kmalloc(sizeof(*cport_count), GFP_KERNEL);
+	if (!cport_count)
+		return -ENOMEM;
+
+	retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+				 REQUEST_CPORT_COUNT,
+				 USB_DIR_IN | USB_TYPE_VENDOR |
+				 USB_RECIP_INTERFACE, 0, 0, cport_count,
+				 sizeof(*cport_count), ES1_TIMEOUT);
+	if (retval < 0) {
+		dev_err(&udev->dev, "Cannot retrieve CPort count: %d\n",
+			retval);
+		goto out;
+	}
+
+	retval = le16_to_cpu(*cport_count);
+
+	/* We need to fit a CPort ID in one byte of a message header */
+	if (retval > U8_MAX) {
+		retval = U8_MAX;
+		dev_warn(&udev->dev, "Limiting number of CPorts to U8_MAX\n");
+	}
+
+out:
+	kfree(cport_count);
+	return retval;
+}
+
 /*
  * The ES1 USB Bridge device contains 4 endpoints
  * 1 Control - usual USB stuff + AP -> SVC messages
@@ -655,14 +688,20 @@
 	int bulk_out = 0;
 	int retval = -ENOMEM;
 	int i;
-
-	/* We need to fit a CPort ID in one byte of a message header */
-	BUILD_BUG_ON(CPORT_ID_MAX > U8_MAX);
+	int num_cports;
 
 	udev = usb_get_dev(interface_to_usbdev(interface));
 
+	num_cports = apb1_get_cport_count(udev);
+	if (num_cports < 0) {
+		usb_put_dev(udev);
+		dev_err(&udev->dev, "Cannot retrieve CPort count: %d\n",
+			num_cports);
+		return num_cports;
+	}
+
 	hd = greybus_create_hd(&es1_driver, &udev->dev, ES1_GBUF_MSG_SIZE_MAX,
-			       CPORT_COUNT);
+			       num_cports);
 	if (IS_ERR(hd)) {
 		usb_put_dev(udev);
 		return PTR_ERR(hd);