On Thu, 2015-07-30 at 15:44 +0200, Johan Hovold wrote:
> On Wed, Jul 22, 2015 at 01:56:14PM -0500, Peter E. Berger wrote:
> > From: "Peter E. Berger" <[email protected]>
> >
> > The io_ti driver fails to download firmware to Edgeport
> > devices such as the EP/416, even when the on-disk firmware image
> > (/lib/firmware/edgeport/down3.bin) is more current than the version
> > on the EP/416. The current download code is broken in a few ways.
> > Notably it mis-uses global variables OperationalMajorVersion and
> > OperationalMinorVersion (reading their values before they've been
> > properly initialized and subsequently initializing them multiple times
> > without synchronization). This patch drops the global variables and
> > replaces the redundant calls to request_firmware()/release_firmware()
> > in download_fw() with a single call pair in edge_startup(); the firmware
> > image pointer is then passed to download_fw() and build_i2c_fw_hdr().
> >
> > Signed-off-by: Peter E. Berger <[email protected]>
> > ---
> > drivers/usb/serial/io_ti.c | 115
> > ++++++++++++++++++++++++++-------------------
> > 1 file changed, 66 insertions(+), 49 deletions(-)
> >
> > diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
> > index 69378a7..6cff12c 100644
> > --- a/drivers/usb/serial/io_ti.c
> > +++ b/drivers/usb/serial/io_ti.c
> > @@ -71,6 +71,25 @@ struct product_info {
> > __u8 hardware_type; /* Type of hardware */
> > } __attribute__((packed));
> >
> > +/*
> > + * Edgeport firmware header
> > + *
> > + * "build_number" has been set to 0 in all three of the images I have
> > + * seen, and Digi Tech Support suggests that it is safe to ignore it.
> > + *
> > + * "length" is the number of bytes of actual data following the header.
> > + *
> > + * "checksum" is the low order byte resulting from adding the values of
> > + * all the data bytes.
> > + */
> > +struct edgeport_fw_hdr {
> > + u8 major_version;
> > + u8 minor_version;
> > + u16 build_number;
> > + u16 length;
>
> These should be __le16.
I'm on the road today, but I'll plan to make this and the other changes
that you and Sergei suggest when I get back tonight, so I hope to have a
v9 patchset to you by tomorrow. At first glance all look easy for me to
implement, but I have a question about one below.
>
> > + u8 checksum;
> > +} __packed;
> > +
> > struct edgeport_port {
> > __u16 uart_base;
> > __u16 dma_address;
>
> > @@ -934,7 +934,8 @@ static int ti_cpu_rev(struct edge_ti_manuf_descriptor
> > *desc)
> > * This routine downloads the main operating code into the TI5052, using
> > the
> > * boot code already burned into E2PROM or ROM.
> > */
> > -static int download_fw(struct edgeport_serial *serial)
> > +static int download_fw(struct edgeport_serial *serial,
> > + const struct firmware *fw)
> > {
> > struct device *dev = &serial->serial->dev->dev;
> > int status = 0;
> > @@ -943,6 +944,17 @@ static int download_fw(struct edgeport_serial *serial)
> > struct usb_interface_descriptor *interface;
> > int download_cur_ver;
> > int download_new_ver;
> > + struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
> > +
> > + if (fw->size < sizeof(struct edgeport_fw_hdr)) {
>
> Missing le16_to_cpu on fw->size.
Hmmm... The fw->size refers to the "size_t size" element of struct
firmware (not to an element of edgeport_fw_hdr). Are you saying that I
should change this to "if (le16_to_cpu(fw->size) < sizeof..." or did I
mistake your meaning?
I'll work on this and the other changes when I get back tonight and hope
to have a new patchset for you by tomorrow.
Thanks.
--Peter
>
> > + dev_err(&serial->serial->interface->dev,
> > + "%s - Incomplete firmware header.\n", __func__);
>
> No need to include the function name here.
>
> > + return -EINVAL;
> > + }
> > +
> > + /* If on-board version is newer, "fw_version" will be updated below. */
> > + serial->fw_version = (fw_hdr->major_version << 8) +
> > + fw_hdr->minor_version;
> >
> > /* This routine is entered by both the BOOT mode and the Download mode
> > * We can determine which code is running by the reading the config
>
> > @@ -2383,6 +2387,9 @@ static int edge_startup(struct usb_serial *serial)
> > {
> > struct edgeport_serial *edge_serial;
> > int status;
> > + const struct firmware *fw;
> > + const char *fw_name = "edgeport/down3.bin";
> > + struct device *dev = &serial->interface->dev;
> >
> > /* create our private serial structure */
> > edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL);
> > @@ -2393,7 +2400,17 @@ static int edge_startup(struct usb_serial *serial)
> > edge_serial->serial = serial;
> > usb_set_serial_data(serial, edge_serial);
> >
> > - status = download_fw(edge_serial);
> > + status = request_firmware(&fw, fw_name, dev);
> > + if (status) {
> > + dev_err(&serial->interface->dev,
>
> Why not use dev here as well?
>
> > + "%s - Failed to load image \"%s\" err %d\n",
> > + __func__, fw_name, status);
>
> You can drop the function name here as well.
>
> > + kfree(edge_serial);
> > + return status;
> > + }
> > +
> > + status = download_fw(edge_serial, fw);
> > + release_firmware(fw);
> > if (status) {
> > kfree(edge_serial);
> > return status;
>
> Thanks,
> Johan
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html