aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorOliver Neukum <oliver@neukum.org>2009-10-07 04:50:23 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-10-09 16:52:09 -0400
commit638325154572ba2113a18669fe3b299caa2dabd9 (patch)
treec562a8460be432facbbba11288edaceba5ecbf1c /drivers
parentb2a5cf1bdc011f5474c72543f9d8116c0f07f452 (diff)
USB: serial: fix assumption that throttle/unthrottle cannot sleep
many serial subdrivers are clearly written as if throttle/unthrottle cannot sleep. This leads to unneeded atomic submissions. This patch converts affected drivers in a way to makes very clear that throttle/unthrottle can sleep. Thus future misdesigns can be avoided and efficiency and reliability improved. This removes any such assumption using GFP_KERNEL and spin_lock_irq() Signed-off-by: Oliver Neukum <oliver@neukum.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/serial/aircable.c10
-rw-r--r--drivers/usb/serial/cypress_m8.c12
-rw-r--r--drivers/usb/serial/empeg.c2
-rw-r--r--drivers/usb/serial/garmin_gps.c12
-rw-r--r--drivers/usb/serial/keyspan_pda.c2
-rw-r--r--drivers/usb/serial/kl5kusb105.c2
-rw-r--r--drivers/usb/serial/mct_u232.c14
-rw-r--r--drivers/usb/serial/symbolserial.c12
-rw-r--r--drivers/usb/serial/visor.c12
-rw-r--r--drivers/usb/serial/whiteheat.c10
10 files changed, 37 insertions, 51 deletions
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
index 2cbfab3716e5..b10ac8409411 100644
--- a/drivers/usb/serial/aircable.c
+++ b/drivers/usb/serial/aircable.c
@@ -554,13 +554,12 @@ static void aircable_throttle(struct tty_struct *tty)
554{ 554{
555 struct usb_serial_port *port = tty->driver_data; 555 struct usb_serial_port *port = tty->driver_data;
556 struct aircable_private *priv = usb_get_serial_port_data(port); 556 struct aircable_private *priv = usb_get_serial_port_data(port);
557 unsigned long flags;
558 557
559 dbg("%s - port %d", __func__, port->number); 558 dbg("%s - port %d", __func__, port->number);
560 559
561 spin_lock_irqsave(&priv->rx_lock, flags); 560 spin_lock_irq(&priv->rx_lock);
562 priv->rx_flags |= THROTTLED; 561 priv->rx_flags |= THROTTLED;
563 spin_unlock_irqrestore(&priv->rx_lock, flags); 562 spin_unlock_irq(&priv->rx_lock);
564} 563}
565 564
566/* Based on ftdi_sio.c unthrottle */ 565/* Based on ftdi_sio.c unthrottle */
@@ -569,14 +568,13 @@ static void aircable_unthrottle(struct tty_struct *tty)
569 struct usb_serial_port *port = tty->driver_data; 568 struct usb_serial_port *port = tty->driver_data;
570 struct aircable_private *priv = usb_get_serial_port_data(port); 569 struct aircable_private *priv = usb_get_serial_port_data(port);
571 int actually_throttled; 570 int actually_throttled;
572 unsigned long flags;
573 571
574 dbg("%s - port %d", __func__, port->number); 572 dbg("%s - port %d", __func__, port->number);
575 573
576 spin_lock_irqsave(&priv->rx_lock, flags); 574 spin_lock_irq(&priv->rx_lock);
577 actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED; 575 actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
578 priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED); 576 priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
579 spin_unlock_irqrestore(&priv->rx_lock, flags); 577 spin_unlock_irq(&priv->rx_lock);
580 578
581 if (actually_throttled) 579 if (actually_throttled)
582 schedule_work(&priv->rx_work); 580 schedule_work(&priv->rx_work);
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index e0a8b715f2f2..a591ebec0f89 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -1155,13 +1155,12 @@ static void cypress_throttle(struct tty_struct *tty)
1155{ 1155{
1156 struct usb_serial_port *port = tty->driver_data; 1156 struct usb_serial_port *port = tty->driver_data;
1157 struct cypress_private *priv = usb_get_serial_port_data(port); 1157 struct cypress_private *priv = usb_get_serial_port_data(port);
1158 unsigned long flags;
1159 1158
1160 dbg("%s - port %d", __func__, port->number); 1159 dbg("%s - port %d", __func__, port->number);
1161 1160
1162 spin_lock_irqsave(&priv->lock, flags); 1161 spin_lock_irq(&priv->lock);
1163 priv->rx_flags = THROTTLED; 1162 priv->rx_flags = THROTTLED;
1164 spin_unlock_irqrestore(&priv->lock, flags); 1163 spin_unlock_irq(&priv->lock);
1165} 1164}
1166 1165
1167 1166
@@ -1170,14 +1169,13 @@ static void cypress_unthrottle(struct tty_struct *tty)
1170 struct usb_serial_port *port = tty->driver_data; 1169 struct usb_serial_port *port = tty->driver_data;
1171 struct cypress_private *priv = usb_get_serial_port_data(port); 1170 struct cypress_private *priv = usb_get_serial_port_data(port);
1172 int actually_throttled, result; 1171 int actually_throttled, result;
1173 unsigned long flags;
1174 1172
1175 dbg("%s - port %d", __func__, port->number); 1173 dbg("%s - port %d", __func__, port->number);
1176 1174
1177 spin_lock_irqsave(&priv->lock, flags); 1175 spin_lock_irq(&priv->lock);
1178 actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED; 1176 actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
1179 priv->rx_flags = 0; 1177 priv->rx_flags = 0;
1180 spin_unlock_irqrestore(&priv->lock, flags); 1178 spin_unlock_irq(&priv->lock);
1181 1179
1182 if (!priv->comm_is_ok) 1180 if (!priv->comm_is_ok)
1183 return; 1181 return;
@@ -1185,7 +1183,7 @@ static void cypress_unthrottle(struct tty_struct *tty)
1185 if (actually_throttled) { 1183 if (actually_throttled) {
1186 port->interrupt_in_urb->dev = port->serial->dev; 1184 port->interrupt_in_urb->dev = port->serial->dev;
1187 1185
1188 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); 1186 result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
1189 if (result) { 1187 if (result) {
1190 dev_err(&port->dev, "%s - failed submitting read urb, " 1188 dev_err(&port->dev, "%s - failed submitting read urb, "
1191 "error %d\n", __func__, result); 1189 "error %d\n", __func__, result);
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 33c9e9cf9eb2..7dd0e3eadbe6 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -391,7 +391,7 @@ static void empeg_unthrottle(struct tty_struct *tty)
391 dbg("%s - port %d", __func__, port->number); 391 dbg("%s - port %d", __func__, port->number);
392 392
393 port->read_urb->dev = port->serial->dev; 393 port->read_urb->dev = port->serial->dev;
394 result = usb_submit_urb(port->read_urb, GFP_ATOMIC); 394 result = usb_submit_urb(port->read_urb, GFP_KERNEL);
395 if (result) 395 if (result)
396 dev_err(&port->dev, 396 dev_err(&port->dev,
397 "%s - failed submitting read urb, error %d\n", 397 "%s - failed submitting read urb, error %d\n",
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 20432d345529..5ac900e5a50e 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -1390,14 +1390,13 @@ static void garmin_throttle(struct tty_struct *tty)
1390{ 1390{
1391 struct usb_serial_port *port = tty->driver_data; 1391 struct usb_serial_port *port = tty->driver_data;
1392 struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); 1392 struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
1393 unsigned long flags;
1394 1393
1395 dbg("%s - port %d", __func__, port->number); 1394 dbg("%s - port %d", __func__, port->number);
1396 /* set flag, data received will be put into a queue 1395 /* set flag, data received will be put into a queue
1397 for later processing */ 1396 for later processing */
1398 spin_lock_irqsave(&garmin_data_p->lock, flags); 1397 spin_lock_irq(&garmin_data_p->lock);
1399 garmin_data_p->flags |= FLAGS_QUEUING|FLAGS_THROTTLED; 1398 garmin_data_p->flags |= FLAGS_QUEUING|FLAGS_THROTTLED;
1400 spin_unlock_irqrestore(&garmin_data_p->lock, flags); 1399 spin_unlock_irq(&garmin_data_p->lock);
1401} 1400}
1402 1401
1403 1402
@@ -1405,13 +1404,12 @@ static void garmin_unthrottle(struct tty_struct *tty)
1405{ 1404{
1406 struct usb_serial_port *port = tty->driver_data; 1405 struct usb_serial_port *port = tty->driver_data;
1407 struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); 1406 struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
1408 unsigned long flags;
1409 int status; 1407 int status;
1410 1408
1411 dbg("%s - port %d", __func__, port->number); 1409 dbg("%s - port %d", __func__, port->number);
1412 spin_lock_irqsave(&garmin_data_p->lock, flags); 1410 spin_lock_irq(&garmin_data_p->lock);
1413 garmin_data_p->flags &= ~FLAGS_THROTTLED; 1411 garmin_data_p->flags &= ~FLAGS_THROTTLED;
1414 spin_unlock_irqrestore(&garmin_data_p->lock, flags); 1412 spin_unlock_irq(&garmin_data_p->lock);
1415 1413
1416 /* in native mode send queued data to tty, in 1414 /* in native mode send queued data to tty, in
1417 serial mode nothing needs to be done here */ 1415 serial mode nothing needs to be done here */
@@ -1419,7 +1417,7 @@ static void garmin_unthrottle(struct tty_struct *tty)
1419 garmin_flush_queue(garmin_data_p); 1417 garmin_flush_queue(garmin_data_p);
1420 1418
1421 if (0 != (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) { 1419 if (0 != (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) {
1422 status = usb_submit_urb(port->read_urb, GFP_ATOMIC); 1420 status = usb_submit_urb(port->read_urb, GFP_KERNEL);
1423 if (status) 1421 if (status)
1424 dev_err(&port->dev, 1422 dev_err(&port->dev,
1425 "%s - failed resubmitting read urb, error %d\n", 1423 "%s - failed resubmitting read urb, error %d\n",
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 257c16cc6b2a..1296a097f5c3 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -290,7 +290,7 @@ static void keyspan_pda_rx_unthrottle(struct tty_struct *tty)
290 /* just restart the receive interrupt URB */ 290 /* just restart the receive interrupt URB */
291 dbg("keyspan_pda_rx_unthrottle port %d", port->number); 291 dbg("keyspan_pda_rx_unthrottle port %d", port->number);
292 port->interrupt_in_urb->dev = port->serial->dev; 292 port->interrupt_in_urb->dev = port->serial->dev;
293 if (usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC)) 293 if (usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL))
294 dbg(" usb_submit_urb(read urb) failed"); 294 dbg(" usb_submit_urb(read urb) failed");
295 return; 295 return;
296} 296}
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index f7373371b137..3a7873806f46 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -951,7 +951,7 @@ static void klsi_105_unthrottle(struct tty_struct *tty)
951 dbg("%s - port %d", __func__, port->number); 951 dbg("%s - port %d", __func__, port->number);
952 952
953 port->read_urb->dev = port->serial->dev; 953 port->read_urb->dev = port->serial->dev;
954 result = usb_submit_urb(port->read_urb, GFP_ATOMIC); 954 result = usb_submit_urb(port->read_urb, GFP_KERNEL);
955 if (result) 955 if (result)
956 dev_err(&port->dev, 956 dev_err(&port->dev,
957 "%s - failed submitting read urb, error %d\n", 957 "%s - failed submitting read urb, error %d\n",
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index ad4998bbf16f..cd009cb280a5 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -777,20 +777,19 @@ static void mct_u232_throttle(struct tty_struct *tty)
777{ 777{
778 struct usb_serial_port *port = tty->driver_data; 778 struct usb_serial_port *port = tty->driver_data;
779 struct mct_u232_private *priv = usb_get_serial_port_data(port); 779 struct mct_u232_private *priv = usb_get_serial_port_data(port);
780 unsigned long flags;
781 unsigned int control_state; 780 unsigned int control_state;
782 781
783 dbg("%s - port %d", __func__, port->number); 782 dbg("%s - port %d", __func__, port->number);
784 783
785 spin_lock_irqsave(&priv->lock, flags); 784 spin_lock_irq(&priv->lock);
786 priv->rx_flags |= THROTTLED; 785 priv->rx_flags |= THROTTLED;
787 if (C_CRTSCTS(tty)) { 786 if (C_CRTSCTS(tty)) {
788 priv->control_state &= ~TIOCM_RTS; 787 priv->control_state &= ~TIOCM_RTS;
789 control_state = priv->control_state; 788 control_state = priv->control_state;
790 spin_unlock_irqrestore(&priv->lock, flags); 789 spin_unlock_irq(&priv->lock);
791 (void) mct_u232_set_modem_ctrl(port->serial, control_state); 790 (void) mct_u232_set_modem_ctrl(port->serial, control_state);
792 } else { 791 } else {
793 spin_unlock_irqrestore(&priv->lock, flags); 792 spin_unlock_irq(&priv->lock);
794 } 793 }
795} 794}
796 795
@@ -799,20 +798,19 @@ static void mct_u232_unthrottle(struct tty_struct *tty)
799{ 798{
800 struct usb_serial_port *port = tty->driver_data; 799 struct usb_serial_port *port = tty->driver_data;
801 struct mct_u232_private *priv = usb_get_serial_port_data(port); 800 struct mct_u232_private *priv = usb_get_serial_port_data(port);
802 unsigned long flags;
803 unsigned int control_state; 801 unsigned int control_state;
804 802
805 dbg("%s - port %d", __func__, port->number); 803 dbg("%s - port %d", __func__, port->number);
806 804
807 spin_lock_irqsave(&priv->lock, flags); 805 spin_lock_irq(&priv->lock);
808 if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) { 806 if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) {
809 priv->rx_flags &= ~THROTTLED; 807 priv->rx_flags &= ~THROTTLED;
810 priv->control_state |= TIOCM_RTS; 808 priv->control_state |= TIOCM_RTS;
811 control_state = priv->control_state; 809 control_state = priv->control_state;
812 spin_unlock_irqrestore(&priv->lock, flags); 810 spin_unlock_irq(&priv->lock);
813 (void) mct_u232_set_modem_ctrl(port->serial, control_state); 811 (void) mct_u232_set_modem_ctrl(port->serial, control_state);
814 } else { 812 } else {
815 spin_unlock_irqrestore(&priv->lock, flags); 813 spin_unlock_irq(&priv->lock);
816 } 814 }
817} 815}
818 816
diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c
index f25e54526843..b282c0f2d8e5 100644
--- a/drivers/usb/serial/symbolserial.c
+++ b/drivers/usb/serial/symbolserial.c
@@ -165,33 +165,31 @@ static void symbol_throttle(struct tty_struct *tty)
165{ 165{
166 struct usb_serial_port *port = tty->driver_data; 166 struct usb_serial_port *port = tty->driver_data;
167 struct symbol_private *priv = usb_get_serial_data(port->serial); 167 struct symbol_private *priv = usb_get_serial_data(port->serial);
168 unsigned long flags;
169 168
170 dbg("%s - port %d", __func__, port->number); 169 dbg("%s - port %d", __func__, port->number);
171 spin_lock_irqsave(&priv->lock, flags); 170 spin_lock_irq(&priv->lock);
172 priv->throttled = true; 171 priv->throttled = true;
173 spin_unlock_irqrestore(&priv->lock, flags); 172 spin_unlock_irq(&priv->lock);
174} 173}
175 174
176static void symbol_unthrottle(struct tty_struct *tty) 175static void symbol_unthrottle(struct tty_struct *tty)
177{ 176{
178 struct usb_serial_port *port = tty->driver_data; 177 struct usb_serial_port *port = tty->driver_data;
179 struct symbol_private *priv = usb_get_serial_data(port->serial); 178 struct symbol_private *priv = usb_get_serial_data(port->serial);
180 unsigned long flags;
181 int result; 179 int result;
182 bool was_throttled; 180 bool was_throttled;
183 181
184 dbg("%s - port %d", __func__, port->number); 182 dbg("%s - port %d", __func__, port->number);
185 183
186 spin_lock_irqsave(&priv->lock, flags); 184 spin_lock_irq(&priv->lock);
187 priv->throttled = false; 185 priv->throttled = false;
188 was_throttled = priv->actually_throttled; 186 was_throttled = priv->actually_throttled;
189 priv->actually_throttled = false; 187 priv->actually_throttled = false;
190 spin_unlock_irqrestore(&priv->lock, flags); 188 spin_unlock_irq(&priv->lock);
191 189
192 priv->int_urb->dev = port->serial->dev; 190 priv->int_urb->dev = port->serial->dev;
193 if (was_throttled) { 191 if (was_throttled) {
194 result = usb_submit_urb(priv->int_urb, GFP_ATOMIC); 192 result = usb_submit_urb(priv->int_urb, GFP_KERNEL);
195 if (result) 193 if (result)
196 dev_err(&port->dev, 194 dev_err(&port->dev,
197 "%s - failed submitting read urb, error %d\n", 195 "%s - failed submitting read urb, error %d\n",
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 8e2d6dd9add0..b9341f0e452b 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -583,12 +583,11 @@ static void visor_throttle(struct tty_struct *tty)
583{ 583{
584 struct usb_serial_port *port = tty->driver_data; 584 struct usb_serial_port *port = tty->driver_data;
585 struct visor_private *priv = usb_get_serial_port_data(port); 585 struct visor_private *priv = usb_get_serial_port_data(port);
586 unsigned long flags;
587 586
588 dbg("%s - port %d", __func__, port->number); 587 dbg("%s - port %d", __func__, port->number);
589 spin_lock_irqsave(&priv->lock, flags); 588 spin_lock_irq(&priv->lock);
590 priv->throttled = 1; 589 priv->throttled = 1;
591 spin_unlock_irqrestore(&priv->lock, flags); 590 spin_unlock_irq(&priv->lock);
592} 591}
593 592
594 593
@@ -596,17 +595,16 @@ static void visor_unthrottle(struct tty_struct *tty)
596{ 595{
597 struct usb_serial_port *port = tty->driver_data; 596 struct usb_serial_port *port = tty->driver_data;
598 struct visor_private *priv = usb_get_serial_port_data(port); 597 struct visor_private *priv = usb_get_serial_port_data(port);
599 unsigned long flags;
600 int result; 598 int result;
601 599
602 dbg("%s - port %d", __func__, port->number); 600 dbg("%s - port %d", __func__, port->number);
603 spin_lock_irqsave(&priv->lock, flags); 601 spin_lock_irq(&priv->lock);
604 priv->throttled = 0; 602 priv->throttled = 0;
605 priv->actually_throttled = 0; 603 priv->actually_throttled = 0;
606 spin_unlock_irqrestore(&priv->lock, flags); 604 spin_unlock_irq(&priv->lock);
607 605
608 port->read_urb->dev = port->serial->dev; 606 port->read_urb->dev = port->serial->dev;
609 result = usb_submit_urb(port->read_urb, GFP_ATOMIC); 607 result = usb_submit_urb(port->read_urb, GFP_KERNEL);
610 if (result) 608 if (result)
611 dev_err(&port->dev, 609 dev_err(&port->dev,
612 "%s - failed submitting read urb, error %d\n", 610 "%s - failed submitting read urb, error %d\n",
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 62424eec33ec..1093d2eb046a 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -949,13 +949,12 @@ static void whiteheat_throttle(struct tty_struct *tty)
949{ 949{
950 struct usb_serial_port *port = tty->driver_data; 950 struct usb_serial_port *port = tty->driver_data;
951 struct whiteheat_private *info = usb_get_serial_port_data(port); 951 struct whiteheat_private *info = usb_get_serial_port_data(port);
952 unsigned long flags;
953 952
954 dbg("%s - port %d", __func__, port->number); 953 dbg("%s - port %d", __func__, port->number);
955 954
956 spin_lock_irqsave(&info->lock, flags); 955 spin_lock_irq(&info->lock);
957 info->flags |= THROTTLED; 956 info->flags |= THROTTLED;
958 spin_unlock_irqrestore(&info->lock, flags); 957 spin_unlock_irq(&info->lock);
959 958
960 return; 959 return;
961} 960}
@@ -966,14 +965,13 @@ static void whiteheat_unthrottle(struct tty_struct *tty)
966 struct usb_serial_port *port = tty->driver_data; 965 struct usb_serial_port *port = tty->driver_data;
967 struct whiteheat_private *info = usb_get_serial_port_data(port); 966 struct whiteheat_private *info = usb_get_serial_port_data(port);
968 int actually_throttled; 967 int actually_throttled;
969 unsigned long flags;
970 968
971 dbg("%s - port %d", __func__, port->number); 969 dbg("%s - port %d", __func__, port->number);
972 970
973 spin_lock_irqsave(&info->lock, flags); 971 spin_lock_irq(&info->lock);
974 actually_throttled = info->flags & ACTUALLY_THROTTLED; 972 actually_throttled = info->flags & ACTUALLY_THROTTLED;
975 info->flags &= ~(THROTTLED | ACTUALLY_THROTTLED); 973 info->flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
976 spin_unlock_irqrestore(&info->lock, flags); 974 spin_unlock_irq(&info->lock);
977 975
978 if (actually_throttled) 976 if (actually_throttled)
979 rx_data_softint(&info->rx_work); 977 rx_data_softint(&info->rx_work);