Remove useless #ifdef RESET_USB_CONFIG code.
Change kalloc / memset to kzalloc
The attach function was not freeing the private data on error
returns. Separate the releasing of urbs and private data and
add a common error exit for attach failure.
Set the board private data pointer to NULL after freeing
the private data.
Reduce console spam by emitting only one attach message.
Change last pr_err in attach to dev_err
Signed-off-by: Dave Penkler <dpenkler@gmail.com>
---
.../gpib/agilent_82357a/agilent_82357a.c | 84 ++++++++-----------
1 file changed, 36 insertions(+), 48 deletions(-)
diff --git a/drivers/staging/gpib/agilent_82357a/agilent_82357a.c b/drivers/staging/gpib/agilent_82357a/agilent_82357a.c
index 2aaccebc3c7b..69f0e490d401 100644
--- a/drivers/staging/gpib/agilent_82357a/agilent_82357a.c
+++ b/drivers/staging/gpib/agilent_82357a/agilent_82357a.c
@@ -1146,25 +1146,6 @@ static int agilent_82357a_setup_urbs(gpib_board_t *board)
return retval;
}
-#ifdef RESET_USB_CONFIG
-static int agilent_82357a_reset_usb_configuration(gpib_board_t *board)
-{
- struct agilent_82357a_priv *a_priv = board->private_data;
- struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
- struct usb_device *usb_dev;
- int retval;
-
- if (!a_priv->bus_interface)
- return -ENODEV;
- usb_dev = interface_to_usbdev(a_priv->bus_interface);
- retval = usb_reset_configuration(usb_dev);
- if (retval)
- dev_err(&usb_dev->dev, "%s: usb_reset_configuration() returned %i\n",
- __func__, retval);
- return retval;
-}
-#endif
-
static void agilent_82357a_cleanup_urbs(struct agilent_82357a_priv *a_priv)
{
if (a_priv && a_priv->bus_interface) {
@@ -1175,15 +1156,23 @@ static void agilent_82357a_cleanup_urbs(struct agilent_82357a_priv *a_priv)
}
};
+static void agilent_82357a_release_urbs(struct agilent_82357a_priv *a_priv)
+{
+ if (a_priv) {
+ usb_free_urb(a_priv->interrupt_urb);
+ a_priv->interrupt_urb = NULL;
+ kfree(a_priv->interrupt_buffer);
+ }
+}
+
static int agilent_82357a_allocate_private(gpib_board_t *board)
{
struct agilent_82357a_priv *a_priv;
- board->private_data = kmalloc(sizeof(struct agilent_82357a_priv), GFP_KERNEL);
+ board->private_data = kzalloc(sizeof(struct agilent_82357a_priv), GFP_KERNEL);
if (!board->private_data)
return -ENOMEM;
a_priv = board->private_data;
- memset(a_priv, 0, sizeof(struct agilent_82357a_priv));
mutex_init(&a_priv->bulk_transfer_lock);
mutex_init(&a_priv->bulk_alloc_lock);
mutex_init(&a_priv->control_alloc_lock);
@@ -1191,11 +1180,11 @@ static int agilent_82357a_allocate_private(gpib_board_t *board)
return 0;
}
-static void agilent_82357a_free_private(struct agilent_82357a_priv *a_priv)
+static void agilent_82357a_free_private(gpib_board_t *board)
{
- usb_free_urb(a_priv->interrupt_urb);
- kfree(a_priv->interrupt_buffer);
- kfree(a_priv);
+ kfree(board->private_data);
+ board->private_data = NULL;
+
}
static int agilent_82357a_init(gpib_board_t *board)
@@ -1342,16 +1331,14 @@ static int agilent_82357a_attach(gpib_board_t *board, const gpib_board_config_t
a_priv->bus_interface = agilent_82357a_driver_interfaces[i];
usb_set_intfdata(agilent_82357a_driver_interfaces[i], board);
usb_dev = interface_to_usbdev(a_priv->bus_interface);
- dev_info(&usb_dev->dev,
- "bus %d dev num %d attached to gpib minor %d, agilent usb interface %i\n",
- usb_dev->bus->busnum, usb_dev->devnum, board->minor, i);
break;
}
}
if (i == MAX_NUM_82357A_INTERFACES) {
- mutex_unlock(&agilent_82357a_hotplug_lock);
- pr_err("No Agilent 82357 gpib adapters found, have you loaded its firmware?\n");
- return -ENODEV;
+ dev_err(board->gpib_dev,
+ "No Agilent 82357 gpib adapters found, have you loaded its firmware?\n");
+ retval = -ENODEV;
+ goto attach_fail;
}
product_id = le16_to_cpu(interface_to_usbdev(a_priv->bus_interface)->descriptor.idProduct);
switch (product_id) {
@@ -1365,21 +1352,13 @@ static int agilent_82357a_attach(gpib_board_t *board, const gpib_board_config_t
break;
default:
dev_err(&usb_dev->dev, "bug, unhandled product_id in switch?\n");
- mutex_unlock(&agilent_82357a_hotplug_lock);
- return -EIO;
- }
-#ifdef RESET_USB_CONFIG
- retval = agilent_82357a_reset_usb_configuration(board);
- if (retval < 0) {
- mutex_unlock(&agilent_82357a_hotplug_lock);
- return retval;
+ retval = -EIO;
+ goto attach_fail;
}
-#endif
+
retval = agilent_82357a_setup_urbs(board);
- if (retval < 0) {
- mutex_unlock(&agilent_82357a_hotplug_lock);
- return retval;
- }
+ if (retval < 0)
+ goto attach_fail;
timer_setup(&a_priv->bulk_timer, agilent_82357a_timeout_handler, 0);
@@ -1388,11 +1367,19 @@ static int agilent_82357a_attach(gpib_board_t *board, const gpib_board_config_t
retval = agilent_82357a_init(board);
if (retval < 0) {
- mutex_unlock(&agilent_82357a_hotplug_lock);
- return retval;
+ agilent_82357a_cleanup_urbs(a_priv);
+ agilent_82357a_release_urbs(a_priv);
+ goto attach_fail;
}
- dev_info(&usb_dev->dev, "%s: attached\n", __func__);
+ dev_info(&usb_dev->dev,
+ "bus %d dev num %d attached to gpib minor %d, agilent usb interface %i\n",
+ usb_dev->bus->busnum, usb_dev->devnum, board->minor, i);
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ return retval;
+
+attach_fail:
+ agilent_82357a_free_private(board);
mutex_unlock(&agilent_82357a_hotplug_lock);
return retval;
}
@@ -1455,7 +1442,8 @@ static void agilent_82357a_detach(gpib_board_t *board)
mutex_lock(&a_priv->bulk_alloc_lock);
mutex_lock(&a_priv->interrupt_alloc_lock);
agilent_82357a_cleanup_urbs(a_priv);
- agilent_82357a_free_private(a_priv);
+ agilent_82357a_release_urbs(a_priv);
+ agilent_82357a_free_private(board);
}
dev_info(board->gpib_dev, "%s: detached\n", __func__);
mutex_unlock(&agilent_82357a_hotplug_lock);
--
2.47.1
This patch does too many things... It should be split up. People
complain about this requirement a lot, but eventually it will become
instinctive. I use `git citool` so I can highlight and click to add
lines to a commit. In this code there were some dev_info() changes
mixed into the unwind code in ->attach() that were hard to separate out
into their own commit but it wasn't too complicated.
On Sat, Jan 18, 2025 at 03:50:46PM +0100, Dave Penkler wrote:
> Remove useless #ifdef RESET_USB_CONFIG code.
>
patch 1.
> Change kalloc / memset to kzalloc
>
patch 2.
> The attach function was not freeing the private data on error
> returns. Separate the releasing of urbs and private data and
> add a common error exit for attach failure.
>
> Set the board private data pointer to NULL after freeing
> the private data.
By setting the private data, this patch actually does fix the
double free that I mentioned earlier. It changes the ->detach into
a no-op if ->attach fails. Needs a Fixes tag. ;)
But I still hope my blog will convince you that the error handling can be
re-written in a better way. It shouldn't matter if ->private_data is
NULL or non-NULL because the caller should only have to handle success
or failure. The caller shouldn't have to handle a dozen different
failure modes:
1) Failure but the ->private_data is NULL
2) Failure but the foo->frob pointer is an error pointer
3) Failure but the foo->frob pointer needs to be freed.
4) Failure but the foo->frob pointer contains other pointers which
need to be freed.
5) ...
It should just be
1) Success: Everything is allocated
2) Failure: Everything is cleaned up and any accesses are probably a
use after free.
>
> Reduce console spam by emitting only one attach message.
>
> Change last pr_err in attach to dev_err
>
These last two can probably be combined into one patch?
> @@ -1388,11 +1367,19 @@ static int agilent_82357a_attach(gpib_board_t *board, const gpib_board_config_t
> retval = agilent_82357a_init(board);
>
> if (retval < 0) {
> - mutex_unlock(&agilent_82357a_hotplug_lock);
> - return retval;
> + agilent_82357a_cleanup_urbs(a_priv);
> + agilent_82357a_release_urbs(a_priv);
> + goto attach_fail;
> }
In my blog talk about how every allocation function should have a
matching free() function. These two functions match
agilent_82357a_setup_urbs() so we should have a single function to
release the urbs.
regards,
dan carpenter
On Mon, Jan 20, 2025 at 10:15:55AM +0300, Dan Carpenter wrote:
> This patch does too many things... It should be split up. People
> complain about this requirement a lot, but eventually it will become
> instinctive. I use `git citool` so I can highlight and click to add
> lines to a commit. In this code there were some dev_info() changes
> mixed into the unwind code in ->attach() that were hard to separate out
> into their own commit but it wasn't too complicated.
>
> On Sat, Jan 18, 2025 at 03:50:46PM +0100, Dave Penkler wrote:
> > Remove useless #ifdef RESET_USB_CONFIG code.
> >
>
> patch 1.
>
> > Change kalloc / memset to kzalloc
> >
>
> patch 2.
>
> > The attach function was not freeing the private data on error
> > returns. Separate the releasing of urbs and private data and
> > add a common error exit for attach failure.
> >
> > Set the board private data pointer to NULL after freeing
> > the private data.
>
> By setting the private data, this patch actually does fix the
> double free that I mentioned earlier. It changes the ->detach into
> a no-op if ->attach fails. Needs a Fixes tag. ;)
>
> But I still hope my blog will convince you that the error handling can be
> re-written in a better way. It shouldn't matter if ->private_data is
> NULL or non-NULL because the caller should only have to handle success
> or failure. The caller shouldn't have to handle a dozen different
> failure modes:
>
> 1) Failure but the ->private_data is NULL
> 2) Failure but the foo->frob pointer is an error pointer
> 3) Failure but the foo->frob pointer needs to be freed.
> 4) Failure but the foo->frob pointer contains other pointers which
> need to be freed.
> 5) ...
>
> It should just be
>
> 1) Success: Everything is allocated
> 2) Failure: Everything is cleaned up and any accesses are probably a
> use after free.
>
> >
> > Reduce console spam by emitting only one attach message.
> >
> > Change last pr_err in attach to dev_err
> >
>
> These last two can probably be combined into one patch?
>
> > @@ -1388,11 +1367,19 @@ static int agilent_82357a_attach(gpib_board_t *board, const gpib_board_config_t
> > retval = agilent_82357a_init(board);
> >
> > if (retval < 0) {
> > - mutex_unlock(&agilent_82357a_hotplug_lock);
> > - return retval;
> > + agilent_82357a_cleanup_urbs(a_priv);
> > + agilent_82357a_release_urbs(a_priv);
> > + goto attach_fail;
> > }
>
> In my blog talk about how every allocation function should have a
> matching free() function. These two functions match
> agilent_82357a_setup_urbs() so we should have a single function to
> release the urbs.
Hi,
I fully agree with you and this is the direction we are pursuing in
the gpib driver code base. We have very long way to go still and
I apologize for not splitting up the changes into multiple patches.
Thanks for the pointer to git citool.
-dave
>
> regards,
> dan carpenter
>
© 2016 - 2026 Red Hat, Inc.