Commit 9df94499 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

greybus: Merge branch alex into Alexandre

This resolves a conflict with es2.c that I fixed up.
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parents fc1a536e 4bc1389d
...@@ -158,7 +158,7 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, ...@@ -158,7 +158,7 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle,
if (!connection) if (!connection)
return NULL; return NULL;
retval = ida_simple_get(id_map, 0, HOST_DEV_CPORT_ID_MAX, GFP_KERNEL); retval = ida_simple_get(id_map, 0, CPORT_ID_MAX, GFP_KERNEL);
if (retval < 0) { if (retval < 0) {
kfree(connection); kfree(connection);
return NULL; return NULL;
......
...@@ -170,6 +170,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver ...@@ -170,6 +170,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver
size_t buffer_size_max) size_t buffer_size_max)
{ {
struct greybus_host_device *hd; struct greybus_host_device *hd;
int ret;
/* /*
* Validate that the driver implements all of the callbacks * Validate that the driver implements all of the callbacks
...@@ -200,12 +201,19 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver ...@@ -200,12 +201,19 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver
if (!hd) if (!hd)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
ida_init(&hd->cport_id_map);
/* Reserve CPort id 0 */
ret = ida_simple_get(&hd->cport_id_map, 0, 1, GFP_KERNEL);
if (ret < 0) {
kfree(hd);
return ERR_PTR(ret);
}
kref_init(&hd->kref); kref_init(&hd->kref);
hd->parent = parent; hd->parent = parent;
hd->driver = driver; hd->driver = driver;
INIT_LIST_HEAD(&hd->interfaces); INIT_LIST_HEAD(&hd->interfaces);
INIT_LIST_HEAD(&hd->connections); INIT_LIST_HEAD(&hd->connections);
ida_init(&hd->cport_id_map);
hd->buffer_size_max = buffer_size_max; hd->buffer_size_max = buffer_size_max;
return hd; return hd;
...@@ -246,7 +254,7 @@ static int __init gb_init(void) ...@@ -246,7 +254,7 @@ static int __init gb_init(void)
if (greybus_disabled()) if (greybus_disabled())
return -ENODEV; return -ENODEV;
BUILD_BUG_ON(HOST_DEV_CPORT_ID_MAX >= (long)CPORT_ID_BAD); BUILD_BUG_ON(CPORT_ID_MAX >= (long)CPORT_ID_BAD);
gb_debugfs_init(); gb_debugfs_init();
......
...@@ -172,6 +172,32 @@ static void free_urb(struct es1_ap_dev *es1, struct urb *urb) ...@@ -172,6 +172,32 @@ static void free_urb(struct es1_ap_dev *es1, struct urb *urb)
usb_free_urb(urb); usb_free_urb(urb);
} }
/*
* We (ab)use the operation-message header pad bytes to transfer the
* cport id in order to minimise overhead.
*/
static void
gb_message_cport_pack(struct gb_operation_msg_hdr *header, u16 cport_id)
{
header->pad[0] = cport_id;
}
/* Clear the pad bytes used for the CPort id */
static void gb_message_cport_clear(struct gb_operation_msg_hdr *header)
{
header->pad[0] = 0;
}
/* Extract the CPort id packed into the header, and clear it */
static u16 gb_message_cport_unpack(struct gb_operation_msg_hdr *header)
{
u16 cport_id = header->pad[0];
gb_message_cport_clear(header);
return cport_id;
}
/* /*
* Returns an opaque cookie value if successful, or a pointer coded * Returns an opaque cookie value if successful, or a pointer coded
* error otherwise. If the caller wishes to cancel the in-flight * error otherwise. If the caller wishes to cancel the in-flight
...@@ -182,21 +208,17 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, ...@@ -182,21 +208,17 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id,
{ {
struct es1_ap_dev *es1 = hd_to_es1(hd); struct es1_ap_dev *es1 = hd_to_es1(hd);
struct usb_device *udev = es1->usb_dev; struct usb_device *udev = es1->usb_dev;
void *buffer;
size_t buffer_size; size_t buffer_size;
int retval; int retval;
struct urb *urb; struct urb *urb;
buffer = message->buffer;
buffer_size = sizeof(*message->header) + message->payload_size;
/* /*
* The data actually transferred will include an indication * The data actually transferred will include an indication
* of where the data should be sent. Do one last check of * of where the data should be sent. Do one last check of
* the target CPort id before filling it in. * the target CPort id before filling it in.
*/ */
if (cport_id == CPORT_ID_BAD) { if (!cport_id_valid(cport_id)) {
pr_err("request to send inbound data buffer\n"); pr_err("invalid destination cport 0x%02x\n", cport_id);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
...@@ -205,21 +227,20 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, ...@@ -205,21 +227,20 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id,
if (!urb) if (!urb)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
/* /* Pack the cport id into the message header */
* We (ab)use the operation-message header pad bytes to transfer the gb_message_cport_pack(message->header, cport_id);
* cport id in order to minimise overhead.
*/ buffer_size = sizeof(*message->header) + message->payload_size;
put_unaligned_le16(cport_id, message->header->pad);
usb_fill_bulk_urb(urb, udev, usb_fill_bulk_urb(urb, udev,
usb_sndbulkpipe(udev, es1->cport_out_endpoint), usb_sndbulkpipe(udev, es1->cport_out_endpoint),
buffer, buffer_size, message->buffer, buffer_size,
cport_out_callback, message); cport_out_callback, message);
retval = usb_submit_urb(urb, gfp_mask); retval = usb_submit_urb(urb, gfp_mask);
if (retval) { if (retval) {
pr_err("error %d submitting URB\n", retval); pr_err("error %d submitting URB\n", retval);
free_urb(es1, urb); free_urb(es1, urb);
put_unaligned_le16(0, message->header->pad); gb_message_cport_clear(message->header);
return ERR_PTR(retval); return ERR_PTR(retval);
} }
...@@ -373,12 +394,16 @@ static void cport_in_callback(struct urb *urb) ...@@ -373,12 +394,16 @@ static void cport_in_callback(struct urb *urb)
goto exit; goto exit;
} }
/* Extract the CPort id, which is packed in the message header */
header = urb->transfer_buffer; header = urb->transfer_buffer;
cport_id = get_unaligned_le16(header->pad); cport_id = gb_message_cport_unpack(header);
put_unaligned_le16(0, header->pad);
greybus_data_rcvd(hd, cport_id, urb->transfer_buffer, if (cport_id_valid(cport_id))
greybus_data_rcvd(hd, cport_id, urb->transfer_buffer,
urb->actual_length); urb->actual_length);
else
dev_err(dev, "%s: invalid cport id 0x%02x received\n",
__func__, cport_id);
exit: exit:
/* put our urb back in the request pool */ /* put our urb back in the request pool */
retval = usb_submit_urb(urb, GFP_ATOMIC); retval = usb_submit_urb(urb, GFP_ATOMIC);
...@@ -394,8 +419,7 @@ static void cport_out_callback(struct urb *urb) ...@@ -394,8 +419,7 @@ static void cport_out_callback(struct urb *urb)
struct es1_ap_dev *es1 = hd_to_es1(hd); struct es1_ap_dev *es1 = hd_to_es1(hd);
int status = check_urb_status(urb); int status = check_urb_status(urb);
/* Clear the pad bytes used for the cport id */ gb_message_cport_clear(message->header);
put_unaligned_le16(0, message->header->pad);
/* /*
* Tell the submitter that the message send (attempt) is * Tell the submitter that the message send (attempt) is
...@@ -556,6 +580,9 @@ static int ap_probe(struct usb_interface *interface, ...@@ -556,6 +580,9 @@ static int ap_probe(struct usb_interface *interface,
u8 ap_intf_id = 0x01; // FIXME - get endo "ID" from the SVC u8 ap_intf_id = 0x01; // FIXME - get endo "ID" from the SVC
u8 svc_interval = 0; u8 svc_interval = 0;
/* We need to fit a CPort ID in one byte of a message header */
BUILD_BUG_ON(CPORT_ID_MAX > U8_MAX);
udev = usb_get_dev(interface_to_usbdev(interface)); udev = usb_get_dev(interface_to_usbdev(interface));
hd = greybus_create_hd(&es1_driver, &udev->dev, ES1_GBUF_MSG_SIZE_MAX); hd = greybus_create_hd(&es1_driver, &udev->dev, ES1_GBUF_MSG_SIZE_MAX);
......
...@@ -265,6 +265,32 @@ static void free_urb(struct es1_ap_dev *es1, struct urb *urb) ...@@ -265,6 +265,32 @@ static void free_urb(struct es1_ap_dev *es1, struct urb *urb)
usb_free_urb(urb); usb_free_urb(urb);
} }
/*
* We (ab)use the operation-message header pad bytes to transfer the
* cport id in order to minimise overhead.
*/
static void
gb_message_cport_pack(struct gb_operation_msg_hdr *header, u16 cport_id)
{
header->pad[0] = cport_id;
}
/* Clear the pad bytes used for the CPort id */
static void gb_message_cport_clear(struct gb_operation_msg_hdr *header)
{
header->pad[0] = 0;
}
/* Extract the CPort id packed into the header, and clear it */
static u16 gb_message_cport_unpack(struct gb_operation_msg_hdr *header)
{
u16 cport_id = header->pad[0];
gb_message_cport_clear(header);
return cport_id;
}
/* /*
* Returns an opaque cookie value if successful, or a pointer coded * Returns an opaque cookie value if successful, or a pointer coded
* error otherwise. If the caller wishes to cancel the in-flight * error otherwise. If the caller wishes to cancel the in-flight
...@@ -275,22 +301,18 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, ...@@ -275,22 +301,18 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id,
{ {
struct es1_ap_dev *es1 = hd_to_es1(hd); struct es1_ap_dev *es1 = hd_to_es1(hd);
struct usb_device *udev = es1->usb_dev; struct usb_device *udev = es1->usb_dev;
void *buffer;
size_t buffer_size; size_t buffer_size;
int retval; int retval;
struct urb *urb; struct urb *urb;
int bulk_ep_set; int bulk_ep_set;
buffer = message->buffer;
buffer_size = sizeof(*message->header) + message->payload_size;
/* /*
* The data actually transferred will include an indication * The data actually transferred will include an indication
* of where the data should be sent. Do one last check of * of where the data should be sent. Do one last check of
* the target CPort id before filling it in. * the target CPort id before filling it in.
*/ */
if (cport_id == CPORT_ID_BAD) { if (!cport_id_valid(cport_id)) {
pr_err("request to send inbound data buffer\n"); pr_err("invalid destination cport 0x%02x\n", cport_id);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
...@@ -299,23 +321,22 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id, ...@@ -299,23 +321,22 @@ static void *message_send(struct greybus_host_device *hd, u16 cport_id,
if (!urb) if (!urb)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
/* /* Pack the cport id into the message header */
* We (ab)use the operation-message header pad bytes to transfer the gb_message_cport_pack(message->header, cport_id);
* cport id in order to minimise overhead.
*/ buffer_size = sizeof(*message->header) + message->payload_size;
put_unaligned_le16(cport_id, message->header->pad);
bulk_ep_set = cport_to_ep(es1, cport_id); bulk_ep_set = cport_to_ep(es1, cport_id);
usb_fill_bulk_urb(urb, udev, usb_fill_bulk_urb(urb, udev,
usb_sndbulkpipe(udev, usb_sndbulkpipe(udev,
es1->cport_out[bulk_ep_set].endpoint), es1->cport_out[bulk_ep_set].endpoint),
buffer, buffer_size, message->buffer, buffer_size,
cport_out_callback, message); cport_out_callback, message);
retval = usb_submit_urb(urb, gfp_mask); retval = usb_submit_urb(urb, gfp_mask);
if (retval) { if (retval) {
pr_err("error %d submitting URB\n", retval); pr_err("error %d submitting URB\n", retval);
free_urb(es1, urb); free_urb(es1, urb);
put_unaligned_le16(0, message->header->pad); gb_message_cport_clear(message->header);
return ERR_PTR(retval); return ERR_PTR(retval);
} }
...@@ -473,12 +494,16 @@ static void cport_in_callback(struct urb *urb) ...@@ -473,12 +494,16 @@ static void cport_in_callback(struct urb *urb)
goto exit; goto exit;
} }
/* Extract the CPort id, which is packed in the message header */
header = urb->transfer_buffer; header = urb->transfer_buffer;
cport_id = get_unaligned_le16(header->pad); cport_id = gb_message_cport_unpack(header);
put_unaligned_le16(0, header->pad);
greybus_data_rcvd(hd, cport_id, urb->transfer_buffer, if (cport_id_valid(cport_id))
greybus_data_rcvd(hd, cport_id, urb->transfer_buffer,
urb->actual_length); urb->actual_length);
else
dev_err(dev, "%s: invalid cport id 0x%02x received\n",
__func__, cport_id);
exit: exit:
/* put our urb back in the request pool */ /* put our urb back in the request pool */
retval = usb_submit_urb(urb, GFP_ATOMIC); retval = usb_submit_urb(urb, GFP_ATOMIC);
...@@ -494,8 +519,7 @@ static void cport_out_callback(struct urb *urb) ...@@ -494,8 +519,7 @@ static void cport_out_callback(struct urb *urb)
struct es1_ap_dev *es1 = hd_to_es1(hd); struct es1_ap_dev *es1 = hd_to_es1(hd);
int status = check_urb_status(urb); int status = check_urb_status(urb);
/* Clear the pad bytes used for the cport id */ gb_message_cport_clear(message->header);
put_unaligned_le16(0, message->header->pad);
/* /*
* Tell the submitter that the message send (attempt) is * Tell the submitter that the message send (attempt) is
...@@ -656,6 +680,9 @@ static int ap_probe(struct usb_interface *interface, ...@@ -656,6 +680,9 @@ static int ap_probe(struct usb_interface *interface,
u8 ap_intf_id = 0x01; // FIXME - get endo "ID" from the SVC u8 ap_intf_id = 0x01; // FIXME - get endo "ID" from the SVC
u8 svc_interval = 0; u8 svc_interval = 0;
/* We need to fit a CPort ID in one byte of a message header */
BUILD_BUG_ON(CPORT_ID_MAX > U8_MAX);
udev = usb_get_dev(interface_to_usbdev(interface)); udev = usb_get_dev(interface_to_usbdev(interface));
hd = greybus_create_hd(&es1_driver, &udev->dev, ES1_GBUF_MSG_SIZE_MAX); hd = greybus_create_hd(&es1_driver, &udev->dev, ES1_GBUF_MSG_SIZE_MAX);
......
...@@ -52,14 +52,14 @@ ...@@ -52,14 +52,14 @@
.serial_number = (s), .serial_number = (s),
/* XXX I couldn't get my Kconfig file to be noticed for out-of-tree build */ /* XXX I couldn't get my Kconfig file to be noticed for out-of-tree build */
#ifndef CONFIG_HOST_DEV_CPORT_ID_MAX #ifndef CONFIG_CPORT_ID_MAX
#define CONFIG_HOST_DEV_CPORT_ID_MAX 128 #define CONFIG_CPORT_ID_MAX 128
#endif /* !CONFIG_HOST_DEV_CPORT_ID_MAX */ #endif /* !CONFIG_CPORT_ID_MAX */
/* Maximum number of CPorts usable by a host device */ /* Maximum number of CPorts usable by a host device */
/* XXX This should really be determined by the AP module manifest */ /* XXX This should really be determined by the AP module manifest */
#define HOST_DEV_CPORT_ID_MAX CONFIG_HOST_DEV_CPORT_ID_MAX #define CPORT_ID_MAX CONFIG_CPORT_ID_MAX
#define CPORT_ID_BAD U16_MAX /* UniPro max id is 4095 */ #define CPORT_ID_BAD U16_MAX /* UniPro max id is 4095 */
/* For SP1 hardware, we are going to "hardcode" each device to have all logical /* For SP1 hardware, we are going to "hardcode" each device to have all logical
* blocks in order to be able to address them as one unified "unit". Then * blocks in order to be able to address them as one unified "unit". Then
...@@ -196,5 +196,10 @@ static inline int is_gb_connection(const struct device *dev) ...@@ -196,5 +196,10 @@ static inline int is_gb_connection(const struct device *dev)
return dev->type == &greybus_connection_type; return dev->type == &greybus_connection_type;
} }
static inline bool cport_id_valid(u16 cport_id)
{
return cport_id && cport_id != CPORT_ID_BAD && cport_id <= CPORT_ID_MAX;
}
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* __LINUX_GREYBUS_H */ #endif /* __LINUX_GREYBUS_H */
...@@ -224,9 +224,12 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) ...@@ -224,9 +224,12 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle)
if (desc_cport->bundle != bundle_id) if (desc_cport->bundle != bundle_id)
continue; continue;
cport_id = le16_to_cpu(desc_cport->id);
if (cport_id > CPORT_ID_MAX)
goto cleanup;
/* Found one. Set up its function structure */ /* Found one. Set up its function structure */
protocol_id = desc_cport->protocol_id; protocol_id = desc_cport->protocol_id;
cport_id = le16_to_cpu(desc_cport->id);
if (!gb_connection_create(bundle, cport_id, protocol_id)) if (!gb_connection_create(bundle, cport_id, protocol_id))
goto cleanup; goto cleanup;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment