From: Michal Nazarewicz <mina86@mina86.com>
To: balbi@ti.com, jackp@codeaurora.org, pheatwol@codeaurora.org
Cc: linux-usb@vger.kernel.org, linux-arm-msm@vger.kernel.org,
benoit@android.com, andrzej.p@samsung.com,
gregkh@linuxfoundation.org, Manu Gautam <mgautam@codeaurora.org>
Subject: Re: [PATCH v4 1/1] usb: gadget: f_fs: Add support for SuperSpeed Mode
Date: Tue, 24 Dec 2013 03:50:54 +0100 [thread overview]
Message-ID: <xa1tbo07t10x.fsf@mina86.com> (raw)
In-Reply-To: <1387799322-26737-1-git-send-email-mgautam@codeaurora.org>
[-- Attachment #1: Type: text/plain, Size: 7574 bytes --]
On Mon, Dec 23 2013, Manu Gautam <mgautam@codeaurora.org> wrote:
> Allow userspace to pass SuperSpeed descriptors and
> handle them in the driver accordingly.
> This change doesn't modify existing desc_header and thereby
> keeps the ABI changes backward compatible i.e. existing
> userspace drivers compiled with old header (functionfs.h)
> would continue to work with the updated kernel.
I'm mostly fine with this patch. If you change __ffs_func_bind_do_descs
as I've described inline, feel free to resend with:
Acked-by: Michal Nazarewicz <mina86@mina86.com>
The other two minor issues are up to you. I don't have strong feelings.
> Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
> ---
> drivers/usb/gadget/f_fs.c | 176 +++++++++++++++++++++++++++++++++++-----------
> drivers/usb/gadget/u_fs.h | 8 ++-
> 2 files changed, 142 insertions(+), 42 deletions(-)
>
> diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
> index 306a2b5..8c7bf04 100644
> --- a/drivers/usb/gadget/f_fs.c
> +++ b/drivers/usb/gadget/f_fs.c
> @@ -1607,22 +1630,58 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
> }
>
> if (likely(hs_count)) {
> - ret = ffs_do_descs(hs_count, data, len,
> + hs_len = ffs_do_descs(hs_count, data, len,
> __ffs_data_do_entity, ffs);
> - if (unlikely(ret < 0))
> + if (unlikely(hs_len < 0)) {
> + ret = hs_len;
> + goto error;
> + }
> +
> + data += hs_len;
> + len -= hs_len;
> + } else {
> + hs_len = 0;
> + }
> +
> + if (len >= 8) {
> + /* Check SS_MAGIC for presence of ss_descs and get SS_COUNT */
> + if (get_unaligned_le32(data) != FUNCTIONFS_SS_DESC_MAGIC)
> + goto einval;
> +
> + ss_count = get_unaligned_le32(data + 4);
> + data += 8;
> + len -= 8;
> + }
> +
> + if (!fs_count && !hs_count && !ss_count)
> + goto einval;
> +
> + if (ss_count) {
> + ss_len = ffs_do_descs(ss_count, data, len,
> + __ffs_data_do_entity, ffs);
> + if (unlikely(ss_len < 0)) {
> + ret = ss_len;
> goto error;
> + }
> + ret = ss_len;
> } else {
> + ss_len = 0;
> ret = 0;
> }
>
> if (unlikely(len != ret))
> goto einval;
>
> - ffs->raw_fs_descs_length = fs_len;
> - ffs->raw_descs_length = fs_len + ret;
> - ffs->raw_descs = _data;
> - ffs->fs_descs_count = fs_count;
> - ffs->hs_descs_count = hs_count;
> + ffs->raw_fs_hs_descs_length = fs_len + hs_len;
> + ffs->raw_ss_descs_length = ss_len;
> + ffs->raw_descs_length = fs_len + hs_len + ss_len;
This can always be calculated as the sum of the other two fields, so
perhaps the redundancy in the structure is not needed, especially as
this is only used in _ffs_func_bind?
> + ffs->raw_descs = _data;
> + ffs->fs_descs_count = fs_count;
> + ffs->hs_descs_count = hs_count;
> + ffs->ss_descs_count = ss_count;
> + /* ss_descs? present @ header + hs_fs_descs + ss_magic + ss_count */
> + if (ffs->ss_descs_count)
> + ffs->raw_ss_descs_offset = 16 +
> ffs->raw_fs_hs_descs_length + 8;
Similarly here, the offset is easily calculated from the other fields.
I don't have strong feelings, but perhaps it would end up being cleaner
if the values were calculated on demand in _ffs_func_bind?
>
> return 0;
>
> @@ -1850,16 +1909,23 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
> * If hs_descriptors is not NULL then we are reading hs
> * descriptors now
> */
> - const int isHS = func->function.hs_descriptors != NULL;
> - unsigned idx;
> + const int is_hs = func->function.hs_descriptors != NULL;
> + const int is_ss = func->function.ss_descriptors != NULL;
> + unsigned ep_desc_id, idx;
>
> if (type != FFS_DESCRIPTOR)
> return 0;
>
> - if (isHS)
> + if (is_ss) {
> + func->function.ss_descriptors[(long)valuep] = desc;
> + ep_desc_id = 2;
> + } else if (is_hs) {
> func->function.hs_descriptors[(long)valuep] = desc;
> - else
> + ep_desc_id = 1;
> + } else {
> func->function.fs_descriptors[(long)valuep] = desc;
> + ep_desc_id = 0;
> + }
I should have caught it in my previous review. Since is_hs and is_ss
are mutually exclusive, it would be better to use ep_desc_id as a single
3-state variable than having two 2-state variables, which may cause some
confusion as to what they actually mean. So how about:
unsigned ed_desc_id, idx;
if (type != FFS_DESCRIPTOR)
return 0;
/*
* If ss_descriptors is not NULL, we are reading super speed
* descriptors; if hs_descriptors is not NULL, we are reading high
* speed descriptors; otherwise, we are reading full speed
* descriptors.
*/
if (func->function.ss_descriptors) {
ed_desc_id = 2;
func->function.ss_descriptors[(long)valuep] = desc;
} else if (func->function.hs_descriptors) {
ed_desc_id = 1;
func->function.ss_descriptors[(long)valuep] = desc;
} else {
ed_desc_id = 0;
func->function.fs_descriptors[(long)valuep] = desc;
}
>
> if (!desc || desc->bDescriptorType != USB_DT_ENDPOINT)
> return 0;
> @@ -1867,13 +1933,13 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
> idx = (ds->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) - 1;
> ffs_ep = func->eps + idx;
>
> - if (unlikely(ffs_ep->descs[isHS])) {
> + if (unlikely(ffs_ep->descs[ep_desc_id])) {
> pr_vdebug("two %sspeed descriptors for EP %d\n",
> - isHS ? "high" : "full",
> + is_ss ? "super" : (is_hs ? "high" : "full"),
With ep_desc_id this would be solved by a static array at the top of the
function:
static const char *const speed_names[] = { "full", "high", "super" };
and a simple
speed_names[ep_desc_id],
> ds->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
> return -EINVAL;
> }
> - ffs_ep->descs[isHS] = ds;
> + ffs_ep->descs[ep_desc_id] = ds;
>
> ffs_dump_mem(": Original ep desc", ds, ds->bLength);
> if (ffs_ep->ep) {
> @@ -2027,15 +2095,16 @@ static int _ffs_func_bind(struct usb_configuration *c,
> full ? ffs->fs_descs_count + 1 : 0);
> vla_item_with_sz(d, struct usb_descriptor_header *, hs_descs,
> high ? ffs->hs_descs_count + 1 : 0);
> + vla_item_with_sz(d, struct usb_descriptor_header *, ss_descs,
> + super ? ffs->ss_descs_count + 1 : 0);
> vla_item_with_sz(d, short, inums, ffs->interfaces_count);
> - vla_item_with_sz(d, char, raw_descs,
> - high ? ffs->raw_descs_length : ffs->raw_fs_descs_length);
> + vla_item_with_sz(d, char, raw_descs, ffs->raw_descs_length);
This means we might allocate space for descriptors that the gadget will
never use. For instance if user space provides super speed descriptors
but gadget only supports high speed. I'm not saying this should stop
the patch, it's a mere observation. The amount of wasted memory is
probably not that big so perhaps it's not worth complicating the code
to save it after all.
> char *vlabuf;
>
> ENTER();
>
> - /* Only high speed but not supported by gadget? */
> - if (unlikely(!(full | high)))
> + /* Has descriptors only for speeds gadget does not support */
> + if (unlikely(!(full | high | super)))
> return -ENOTSUPP;
>
> /* Allocate a single chunk, less management later on */
--
Best regards, _ _
.o. | Liege of Serenely Enlightened Majesty of o' \,=./ `o
..o | Computer Science, Michał “mina86” Nazarewicz (o o)
ooo +--<mpn@google.com>--<xmpp:mina86@jabber.org>--ooO--(_)--Ooo--
[-- Attachment #2.1: Type: text/plain, Size: 0 bytes --]
[-- Attachment #2.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 835 bytes --]
next prev parent reply other threads:[~2013-12-24 2:51 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-12-23 11:48 [PATCH v4 1/1] usb: gadget: f_fs: Add support for SuperSpeed Mode Manu Gautam
2013-12-23 17:00 ` Felipe Balbi
2013-12-24 2:50 ` Michal Nazarewicz [this message]
2013-12-24 9:35 ` Manu Gautam
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=xa1tbo07t10x.fsf@mina86.com \
--to=mina86@mina86.com \
--cc=andrzej.p@samsung.com \
--cc=balbi@ti.com \
--cc=benoit@android.com \
--cc=gregkh@linuxfoundation.org \
--cc=jackp@codeaurora.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=mgautam@codeaurora.org \
--cc=pheatwol@codeaurora.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.