mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-12 19:44:51 -04:00
staging: gpib: Fix Oops after disconnect in agilent usb
If the agilent usb dongle is disconnected subsequent calls to the
driver cause a NULL dereference Oops as the bus_interface
is set to NULL on disconnect.
This problem was introduced by setting usb_dev from the bus_interface
for dev_xxx messages.
Previously bus_interface was checked for NULL only in the functions
directly calling usb_fill_bulk_urb or usb_control_msg.
Check for valid bus_interface on all interface entry points
and return -ENODEV if it is NULL.
Fixes: fbae7090f3 ("staging: gpib: Update messaging and usb_device refs in agilent_usb")
Cc: stable <stable@kernel.org>
Signed-off-by: Dave Penkler <dpenkler@gmail.com>
Link: https://lore.kernel.org/r/20250222204515.5104-1-dpenkler@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
a239c6e91b
commit
8491e73a52
@@ -427,7 +427,7 @@ static int agilent_82357a_read(gpib_board_t *board, uint8_t *buffer, size_t leng
|
||||
{
|
||||
int retval;
|
||||
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;
|
||||
u8 *out_data, *in_data;
|
||||
int out_data_length, in_data_length;
|
||||
int bytes_written, bytes_read;
|
||||
@@ -438,6 +438,10 @@ static int agilent_82357a_read(gpib_board_t *board, uint8_t *buffer, size_t leng
|
||||
|
||||
*nbytes = 0;
|
||||
*end = 0;
|
||||
|
||||
if (!a_priv->bus_interface)
|
||||
return -ENODEV;
|
||||
usb_dev = interface_to_usbdev(a_priv->bus_interface);
|
||||
out_data_length = 0x9;
|
||||
out_data = kmalloc(out_data_length, GFP_KERNEL);
|
||||
if (!out_data)
|
||||
@@ -534,7 +538,7 @@ static ssize_t agilent_82357a_generic_write(gpib_board_t *board, uint8_t *buffer
|
||||
{
|
||||
int retval;
|
||||
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;
|
||||
u8 *out_data = NULL;
|
||||
u8 *status_data = NULL;
|
||||
int out_data_length;
|
||||
@@ -545,6 +549,10 @@ static ssize_t agilent_82357a_generic_write(gpib_board_t *board, uint8_t *buffer
|
||||
struct agilent_82357a_register_pairlet read_reg;
|
||||
|
||||
*bytes_written = 0;
|
||||
if (!a_priv->bus_interface)
|
||||
return -ENODEV;
|
||||
|
||||
usb_dev = interface_to_usbdev(a_priv->bus_interface);
|
||||
out_data_length = length + 0x8;
|
||||
out_data = kmalloc(out_data_length, GFP_KERNEL);
|
||||
if (!out_data)
|
||||
@@ -697,9 +705,13 @@ int agilent_82357a_take_control_internal(gpib_board_t *board, int synchronous)
|
||||
|
||||
static int agilent_82357a_take_control(gpib_board_t *board, int synchronous)
|
||||
{
|
||||
struct agilent_82357a_priv *a_priv = board->private_data;
|
||||
const int timeout = 10;
|
||||
int i;
|
||||
|
||||
if (!a_priv->bus_interface)
|
||||
return -ENODEV;
|
||||
|
||||
/* It looks like the 9914 does not handle tcs properly.
|
||||
* See comment above tms9914_take_control_workaround() in
|
||||
* drivers/gpib/tms9914/tms9914_aux.c
|
||||
@@ -723,10 +735,14 @@ static int agilent_82357a_take_control(gpib_board_t *board, int synchronous)
|
||||
static int agilent_82357a_go_to_standby(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;
|
||||
struct agilent_82357a_register_pairlet write;
|
||||
int retval;
|
||||
|
||||
if (!a_priv->bus_interface)
|
||||
return -ENODEV;
|
||||
|
||||
usb_dev = interface_to_usbdev(a_priv->bus_interface);
|
||||
write.address = AUXCR;
|
||||
write.value = AUX_GTS;
|
||||
retval = agilent_82357a_write_registers(a_priv, &write, 1);
|
||||
@@ -739,11 +755,15 @@ static int agilent_82357a_go_to_standby(gpib_board_t *board)
|
||||
static void agilent_82357a_request_system_control(gpib_board_t *board, int request_control)
|
||||
{
|
||||
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;
|
||||
struct agilent_82357a_register_pairlet writes[2];
|
||||
int retval;
|
||||
int i = 0;
|
||||
|
||||
if (!a_priv->bus_interface)
|
||||
return; // -ENODEV;
|
||||
|
||||
usb_dev = interface_to_usbdev(a_priv->bus_interface);
|
||||
/* 82357B needs bit to be set in 9914 AUXCR register */
|
||||
writes[i].address = AUXCR;
|
||||
if (request_control) {
|
||||
@@ -767,10 +787,14 @@ static void agilent_82357a_request_system_control(gpib_board_t *board, int reque
|
||||
static void agilent_82357a_interface_clear(gpib_board_t *board, int assert)
|
||||
{
|
||||
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;
|
||||
struct agilent_82357a_register_pairlet write;
|
||||
int retval;
|
||||
|
||||
if (!a_priv->bus_interface)
|
||||
return; // -ENODEV;
|
||||
|
||||
usb_dev = interface_to_usbdev(a_priv->bus_interface);
|
||||
write.address = AUXCR;
|
||||
write.value = AUX_SIC;
|
||||
if (assert) {
|
||||
@@ -785,10 +809,14 @@ static void agilent_82357a_interface_clear(gpib_board_t *board, int assert)
|
||||
static void agilent_82357a_remote_enable(gpib_board_t *board, int enable)
|
||||
{
|
||||
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;
|
||||
struct agilent_82357a_register_pairlet write;
|
||||
int retval;
|
||||
|
||||
if (!a_priv->bus_interface)
|
||||
return; //-ENODEV;
|
||||
|
||||
usb_dev = interface_to_usbdev(a_priv->bus_interface);
|
||||
write.address = AUXCR;
|
||||
write.value = AUX_SRE;
|
||||
if (enable)
|
||||
@@ -804,6 +832,8 @@ static int agilent_82357a_enable_eos(gpib_board_t *board, uint8_t eos_byte, int
|
||||
{
|
||||
struct agilent_82357a_priv *a_priv = board->private_data;
|
||||
|
||||
if (!a_priv->bus_interface)
|
||||
return -ENODEV;
|
||||
if (compare_8_bits == 0)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
@@ -822,10 +852,13 @@ static void agilent_82357a_disable_eos(gpib_board_t *board)
|
||||
static unsigned int agilent_82357a_update_status(gpib_board_t *board, unsigned int clear_mask)
|
||||
{
|
||||
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;
|
||||
struct agilent_82357a_register_pairlet address_status, bus_status;
|
||||
int retval;
|
||||
|
||||
if (!a_priv->bus_interface)
|
||||
return -ENODEV;
|
||||
usb_dev = interface_to_usbdev(a_priv->bus_interface);
|
||||
board->status &= ~clear_mask;
|
||||
if (a_priv->is_cic)
|
||||
set_bit(CIC_NUM, &board->status);
|
||||
@@ -885,6 +918,9 @@ static int agilent_82357a_primary_address(gpib_board_t *board, unsigned int addr
|
||||
struct agilent_82357a_register_pairlet write;
|
||||
int retval;
|
||||
|
||||
if (!a_priv->bus_interface)
|
||||
return -ENODEV;
|
||||
usb_dev = interface_to_usbdev(a_priv->bus_interface);
|
||||
// put primary address in address0
|
||||
write.address = ADR;
|
||||
write.value = address & ADDRESS_MASK;
|
||||
@@ -906,11 +942,14 @@ static int agilent_82357a_secondary_address(gpib_board_t *board, unsigned int ad
|
||||
static int agilent_82357a_parallel_poll(gpib_board_t *board, uint8_t *result)
|
||||
{
|
||||
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;
|
||||
struct agilent_82357a_register_pairlet writes[2];
|
||||
struct agilent_82357a_register_pairlet read;
|
||||
int retval;
|
||||
|
||||
if (!a_priv->bus_interface)
|
||||
return -ENODEV;
|
||||
usb_dev = interface_to_usbdev(a_priv->bus_interface);
|
||||
// execute parallel poll
|
||||
writes[0].address = AUXCR;
|
||||
writes[0].value = AUX_CS | AUX_RPP;
|
||||
@@ -975,11 +1014,14 @@ static void agilent_82357a_return_to_local(gpib_board_t *board)
|
||||
static int agilent_82357a_line_status(const 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;
|
||||
struct agilent_82357a_register_pairlet bus_status;
|
||||
int retval;
|
||||
int status = ValidALL;
|
||||
|
||||
if (!a_priv->bus_interface)
|
||||
return -ENODEV;
|
||||
usb_dev = interface_to_usbdev(a_priv->bus_interface);
|
||||
bus_status.address = BSR;
|
||||
retval = agilent_82357a_read_registers(a_priv, &bus_status, 1, 0);
|
||||
if (retval) {
|
||||
@@ -1025,10 +1067,13 @@ static unsigned short nanosec_to_fast_talker_bits(unsigned int *nanosec)
|
||||
static unsigned int agilent_82357a_t1_delay(gpib_board_t *board, unsigned int nanosec)
|
||||
{
|
||||
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;
|
||||
struct agilent_82357a_register_pairlet write;
|
||||
int retval;
|
||||
|
||||
if (!a_priv->bus_interface)
|
||||
return -ENODEV;
|
||||
usb_dev = interface_to_usbdev(a_priv->bus_interface);
|
||||
write.address = FAST_TALKER_T1;
|
||||
write.value = nanosec_to_fast_talker_bits(&nanosec);
|
||||
retval = agilent_82357a_write_registers(a_priv, &write, 1);
|
||||
|
||||
Reference in New Issue
Block a user