5.13.6-rc1 review
Greg Kroah-Hartman
maintainerPATCH 161/223 usb: hub: Disable USB 3 device initiated lpm if exit latency is too high
In reply to Greg Kroah-HartmanFrom: Mathias Nyman <[email protected]>
commit 1b7f56fbc7a1b66967b6114d1b5f5a257c3abae6 upstream.
The device initiated link power management U1/U2 states should not be enabled in case the system exit latency plus one bus interval (125us) is greater than the shortest service interval of any periodic endpoint.
This is the case for both U1 and U2 sytstem exit latencies and link states.
See USB 3.2 section 9.4.9 "Set Feature" for more details
Note, before this patch the host and device initiated U1/U2 lpm states were both enabled with lpm. After this patch it's possible to end up with only host inititated U1/U2 lpm in case the exit latencies won't allow device initiated lpm.
If this case we still want to set the udev->usb3_lpm_ux_enabled flag so that sysfs users can see the link may go to U1/U2.
--- drivers/usb/core/hub.c | 68 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 12 deletions(-)
drivers/usb/core/hub.c +56 -12
@@ -4091,6 +4091,47 @@ static int usb_set_lpm_timeout(struct us }/* +* Don't allow device intiated U1/U2 if the system exit latency + one bus +* interval is greater than the minimum service interval of any active +* periodic endpoint. See USB 3.2 section 9.4.9 +*/ +static bool usb_device_may_initiate_lpm (struct usb_device *udev, +enum usb3_link_state state) +{ +unsigned int sel;/* us */ +int i, j; + +if (state ==USB3_LPM_U1 ) + sel =DIV_ROUND_UP (udev->u1_params.sel,1000 ); +else if (state ==USB3_LPM_U2 ) + sel =DIV_ROUND_UP (udev->u2_params.sel,1000 ); +else +return false; + +for (i =0 ; i < udev->actconfig->desc.bNumInterfaces; i++) { +struct usb_interface *intf; +struct usb_endpoint_descriptor *desc; +unsigned int interval; + + intf = udev->actconfig->interface[i]; +if (!intf) +continue ; + +for (j =0 ; j < intf->cur_altsetting->desc.bNumEndpoints; j++) { + desc = &intf->cur_altsetting->endpoint[j].desc; + +if (usb_endpoint_xfer_int (desc) || +usb_endpoint_xfer_isoc (desc)) { + interval = (1 << (desc->bInterval -1 )) *125 ; +if (sel +125 > interval) +return false; + } + } + } +return true; +} + +/* * Enable the hub-initiated U1/U2 idle timeouts, and enable device-initiated * U1/U2 entry. *
@@ -4162,20 +4203,23 @@ static void usb_enable_link_state(struct* U1/U2_ENABLE */ if (udev->actconfig && -usb_set_device_initiated_lpm (udev, state, true) ==0 ) { -if (state ==USB3_LPM_U1 ) - udev->usb3_lpm_u1_enabled =1 ; -else if (state ==USB3_LPM_U2 ) - udev->usb3_lpm_u2_enabled =1 ; - }else { -/* Don't request U1/U2 entry if the device -* cannot transition to U1/U2. -*/ -usb_set_lpm_timeout (udev, state,0 ); - hcd->driver->disable_usb3_lpm_timeout (hcd, udev, state); +usb_device_may_initiate_lpm (udev, state)) { +if (usb_set_device_initiated_lpm (udev, state, true)) { +/* +* Request to enable device initiated U1/U2 failed, +* better to turn off lpm in this case. +*/ +usb_set_lpm_timeout (udev, state,0 ); + hcd->driver->disable_usb3_lpm_timeout (hcd, udev, state); +return ; + } } -} +if (state ==USB3_LPM_U1 ) + udev->usb3_lpm_u1_enabled =1 ; +else if (state ==USB3_LPM_U2 ) + udev->usb3_lpm_u2_enabled =1 ; +}/* * Disable the hub-initiated U1/U2 idle timeouts, and disable device-initiated * U1/U2 entry.
Greg Kroah-Hartman
maintainerPATCH 162/223 usb: hub: Fix link power management max exit latency (MEL) calculations
In reply to Greg Kroah-HartmanFrom: Mathias Nyman <[email protected]>
commit 1bf2761c837571a66ec290fb66c90413821ffda2 upstream.
Maximum Exit Latency (MEL) value is used by host to know how much in advance it needs to start waking up a U1/U2 suspended link in order to service a periodic transfer in time.
Current MEL calculation only includes the time to wake up the path from U1/U2 to U0. This is called tMEL1 in USB 3.1 section C 1.5.2
Total MEL = tMEL1 + tMEL2 +tMEL3 + tMEL4 which should additinally include:
- tMEL2 which is the time it takes for PING message to reach device
- tMEL3 time for device to process the PING and submit a PING_RESPONSE
- tMEL4 time for PING_RESPONSE to traverse back upstream to host.
Add the missing tMEL2, tMEL3 and tMEL4 to MEL calculation.
--- drivers/usb/core/hub.c | 52 ++++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 24 deletions(-)
drivers/usb/core/hub.c +28 -24
@@ -48,6 +48,7 @@#define USB_TP_TRANSMISSION_DELAY 40/* ns */ #define USB_TP_TRANSMISSION_DELAY_MAX 65535/* ns */ +#define USB_PING_RESPONSE_TIME 400/* ns */ /* Protect struct usb_device->state and ->children members * Note: Both are also protected by ->dev.sem, except that ->state can
@@ -182,8 +183,9 @@ int usb_device_supports_lpm(struct usb_d }/* -* Set the Maximum Exit Latency (MEL) for the host to initiate a transition from -* either U1 or U2. +* Set the Maximum Exit Latency (MEL) for the host to wakup up the path from +* U1/U2, send a PING to the device and receive a PING_RESPONSE. +* See USB 3.1 section C.1.5.2 */ static void usb_set_lpm_mel(struct usb_device *udev, struct usb3_lpm_parameters *udev_lpm_params,
@@ -193,35 +195,37 @@ static void usb_set_lpm_mel(struct usb_d unsigned int hub_exit_latency) {unsigned int total_mel; -unsigned int device_mel; -unsigned int hub_mel;/* -* Calculate the time it takes to transition all links from the roothub -* to the parent hub into U0. The parent hub must then decode the -* packet (hub header decode latency) to figure out which port it was -* bound for. -* -* The Hub Header decode latency is expressed in 0.1us intervals (0x1 -* means 0.1us). Multiply that by 100 to get nanoseconds. +* tMEL1. time to transition path from host to device into U0. +* MEL for parent already contains the delay up to parent, so only add +* the exit latency for the last link (pick the slower exit latency), +* and the hub header decode latency. See USB 3.1 section C 2.2.1 +* Store MEL in nanoseconds */ total_mel = hub_lpm_params->mel + - (hub->descriptor->u.ss.bHubHdrDecLat *100 ); +max (udev_exit_latency, hub_exit_latency) *1000 + + hub->descriptor->u.ss.bHubHdrDecLat *100 ;/* -* How long will it take to transition the downstream hub's port into -* U0? The greater of either the hub exit latency or the device exit -* latency. -* -* The BOS U1/U2 exit latencies are expressed in 1us intervals. -* Multiply that by 1000 to get nanoseconds. +* tMEL2. Time to submit PING packet. Sum of tTPTransmissionDelay for +* each link + wHubDelay for each hub. Add only for last link. +* tMEL4, the time for PING_RESPONSE to traverse upstream is similar. +* Multiply by 2 to include it as well. */ - device_mel = udev_exit_latency *1000 ; - hub_mel = hub_exit_latency *1000 ; -if (device_mel > hub_mel) - total_mel += device_mel; -else - total_mel += hub_mel; + total_mel += (__le16_to_cpu (hub->descriptor->u.ss.wHubDelay) + +USB_TP_TRANSMISSION_DELAY ) *2 ; + +/* +* tMEL3, tPingResponse. Time taken by device to generate PING_RESPONSE +* after receiving PING. Also add 2100ns as stated in USB 3.1 C 1.5.2.4 +* to cover the delay if the PING_RESPONSE is queued behind a Max Packet +* Size DP. +* Note these delays should be added only once for the entire path, so +* add them to the MEL of the device connected to the roothub. +*/ +if (!hub->hdev->parent) + total_mel +=USB_PING_RESPONSE_TIME +2100 ; udev_lpm_params->mel = total_mel; }
Greg Kroah-Hartman
maintainerPATCH 163/223 USB: usb-storage: Add LaCie Rugged USB3-FW to IGNORE_UAS
In reply to Greg Kroah-HartmanFrom: Julian Sikorski <[email protected]>
commit 6abf2fe6b4bf6e5256b80c5817908151d2d33e9f upstream.
LaCie Rugged USB3-FW appears to be incompatible with UAS. It generates errors like:
[ 1151.582598] sd 14:0:0:0: tag#16 uas_eh_abort_handler 0 uas-tag 1 inflight: IN [ 1151.582602] sd 14:0:0:0: tag#16 CDB: Report supported operation codes a3 0c 01 12 00 00 00 00 02 00 00 00 [ 1151.588594] scsi host14: uas_eh_device_reset_handler start [ 1151.710482] usb 2-4: reset SuperSpeed Gen 1 USB device number 2 using xhci_hcd [ 1151.741398] scsi host14: uas_eh_device_reset_handler success [ 1181.785534] scsi host14: uas_eh_device_reset_handler start
--- drivers/usb/storage/unusual_uas.h | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/usb/storage/unusual_uas.h +7 -0
@@ -45,6 +45,13 @@ UNUSUAL_DEV(0x059f, 0x105f, 0x0000, 0x99 USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_REPORT_OPCODES | US_FL_NO_SAME), +/* Reported-by: Julian Sikorski <[email protected]> */ +UNUSUAL_DEV (0x059f ,0x1061 ,0x0000 ,0x9999 , +"LaCie" , +"Rugged USB3-FW" , +USB_SC_DEVICE ,USB_PR_DEVICE ,NULL , + US_FL_IGNORE_UAS), +/* * Apricorn USB3 dongle sometimes returns "USBSUSBSUSBS" in response to SCSI * commands in UAS mode. Observed with the 1.28 firmware; are there others?
Greg Kroah-Hartman
maintainerPATCH 164/223 usb: max-3421: Prevent corruption of freed memory
In reply to Greg Kroah-HartmanFrom: Mark Tomlinson <[email protected]>
commit b5fdf5c6e6bee35837e160c00ac89327bdad031b upstream.
The MAX-3421 USB driver remembers the state of the USB toggles for a device/endpoint. To save SPI writes, this was only done when a new device/endpoint was being used. Unfortunately, if the old device was removed, this would cause writes to freed memory.
To fix this, a simpler scheme is used. The toggles are read from hardware when a URB is completed, and the toggles are always written to hardware when any URB transaction is started. This will cause a few more SPI transactions, but no causes kernel panics.
--- drivers/usb/host/max3421-hcd.c | 44 +++++++++++++---------------------------- 1 file changed, 14 insertions(+), 30 deletions(-)
drivers/usb/host/max3421-hcd.c +14 -30
@@ -153,8 +153,6 @@ struct max3421_hcd {*/ struct urb *curr_urb;enum scheduling_pass sched_pass; -struct usb_device *loaded_dev;/* dev that's loaded into the chip */ -int loaded_epnum;/* epnum whose toggles are loaded */ int urb_done;/* > 0 -> no errors, < 0: errno */ size_t curr_len;u8 hien;
@@ -492,39 +490,17 @@ max3421_set_speed(struct usb_hcd *hcd, s* Caller must NOT hold HCD spinlock. */ static void -max3421_set_address (struct usb_hcd *hcd,struct usb_device *dev,int epnum, -int force_toggles) +max3421_set_address (struct usb_hcd *hcd,struct usb_device *dev,int epnum) { -struct max3421_hcd *max3421_hcd =hcd_to_max3421 (hcd); -int old_epnum, same_ep, rcvtog, sndtog; -struct usb_device *old_dev; +int rcvtog, sndtog;u8 hctl; - old_dev = max3421_hcd->loaded_dev; - old_epnum = max3421_hcd->loaded_epnum; - - same_ep = (dev == old_dev && epnum == old_epnum); -if (same_ep && !force_toggles) -return ; - -if (old_dev && !same_ep) { -/* save the old end-points toggles: */ -u8 hrsl =spi_rd8 (hcd,MAX3421_REG_HRSL ); - - rcvtog = (hrsl >>MAX3421_HRSL_RCVTOGRD_BIT ) &1 ; - sndtog = (hrsl >>MAX3421_HRSL_SNDTOGRD_BIT ) &1 ; - -/* no locking: HCD (i.e., we) own toggles, don't we? */ -usb_settoggle (old_dev, old_epnum,0 , rcvtog); -usb_settoggle (old_dev, old_epnum,1 , sndtog); - }/* setup new endpoint's toggle bits: */ rcvtog =usb_gettoggle (dev, epnum,0 ); sndtog =usb_gettoggle (dev, epnum,1 ); hctl = (BIT (rcvtog +MAX3421_HCTL_RCVTOG0_BIT ) |BIT (sndtog +MAX3421_HCTL_SNDTOG0_BIT )); - max3421_hcd->loaded_epnum = epnum;spi_wr8 (hcd,MAX3421_REG_HCTL , hctl);/*
@@ -532,7 +508,6 @@ max3421_set_address(struct usb_hcd *hcd,* address-assignment so it's best to just always load the * address whenever the end-point changed/was forced. */ - max3421_hcd->loaded_dev = dev;spi_wr8 (hcd,MAX3421_REG_PERADDR , dev->devnum); }
@@ -667,7 +642,7 @@ max3421_select_and_start_urb(struct usb_struct max3421_hcd *max3421_hcd =hcd_to_max3421 (hcd);struct urb *urb, *curr_urb =NULL ;struct max3421_ep *max3421_ep; -int epnum, force_toggles =0 ; +int epnum;struct usb_host_endpoint *ep;struct list_head *pos;unsigned long flags;
@@ -777,7 +752,6 @@ done:usb_settoggle (urb->dev, epnum,0 ,1 );usb_settoggle (urb->dev, epnum,1 ,1 ); max3421_ep->pkt_state =PKT_STATE_SETUP ; - force_toggles =1 ; }else max3421_ep->pkt_state =PKT_STATE_TRANSFER ; }
@@ -785,7 +759,7 @@ done:spin_unlock_irqrestore (&max3421_hcd->lock, flags); max3421_ep->last_active = max3421_hcd->frame_number; -max3421_set_address (hcd, urb->dev, epnum, force_toggles); +max3421_set_address (hcd, urb->dev, epnum);max3421_set_speed (hcd, urb->dev);max3421_next_transfer (hcd,0 );return 1 ;
@@ -1380,6 +1354,16 @@ max3421_urb_done(struct usb_hcd *hcd) status =0 ; urb = max3421_hcd->curr_urb;if (urb) { +/* save the old end-points toggles: */ +u8 hrsl =spi_rd8 (hcd,MAX3421_REG_HRSL ); +int rcvtog = (hrsl >>MAX3421_HRSL_RCVTOGRD_BIT ) &1 ; +int sndtog = (hrsl >>MAX3421_HRSL_SNDTOGRD_BIT ) &1 ; +int epnum =usb_endpoint_num (&urb->ep->desc); + +/* no locking: HCD (i.e., we) own toggles, don't we? */ +usb_settoggle (urb->dev, epnum,0 , rcvtog); +usb_settoggle (urb->dev, epnum,1 , sndtog); + max3421_hcd->curr_urb =NULL ;spin_lock_irqsave (&max3421_hcd->lock, flags);usb_hcd_unlink_urb_from_ep (hcd, urb);
Greg Kroah-Hartman
maintainerPATCH 165/223 usb: renesas_usbhs: Fix superfluous irqs happen after usb_pkt_pop()
In reply to Greg Kroah-HartmanFrom: Yoshihiro Shimoda <[email protected]>
commit 5719df243e118fb343725e8b2afb1637e1af1373 upstream.
This driver has a potential issue which this driver is possible to cause superfluous irqs after usb_pkt_pop() is called. So, after the commit 3af32605289e ("usb: renesas_usbhs: fix error return code of usbhsf_pkt_handler()") had been applied, we could observe the following error happened when we used g_audio.
renesas_usbhs e6590000.usb: irq_ready run_error 1 : -22
To fix the issue, disable the tx or rx interrupt in usb_pkt_pop().
--- drivers/usb/renesas_usbhs/fifo.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/usb/renesas_usbhs/fifo.c +7 -0
@@ -101,6 +101,8 @@ static struct dma_chan *usbhsf_dma_chan_#define usbhsf_dma_map (p) __usbhsf_dma_map_ctrl(p, 1)#define usbhsf_dma_unmap (p) __usbhsf_dma_map_ctrl(p, 0)static int __usbhsf_dma_map_ctrl (struct usbhs_pkt *pkt,int map); +static void usbhsf_tx_irq_ctrl (struct usbhs_pipe *pipe,int enable); +static void usbhsf_rx_irq_ctrl (struct usbhs_pipe *pipe,int enable);struct usbhs_pkt *usbhs_pkt_pop (struct usbhs_pipe *pipe,struct usbhs_pkt *pkt) {struct usbhs_priv *priv =usbhs_pipe_to_priv (pipe);
@@ -123,6 +125,11 @@ struct usbhs_pkt *usbhs_pkt_pop(struct uif (chan) {dmaengine_terminate_all (chan);usbhsf_dma_unmap (pkt); + }else { +if (usbhs_pipe_is_dir_in (pipe)) +usbhsf_rx_irq_ctrl (pipe,0 ); +else +usbhsf_tx_irq_ctrl (pipe,0 ); }usbhs_pipe_clear_without_sequence (pipe,0 ,0 );
Greg Kroah-Hartman
maintainerPATCH 166/223 USB: serial: option: add support for u-blox LARA-R6 family
In reply to Greg Kroah-HartmanFrom: Marco De Marco <[email protected]>
commit 94b619a07655805a1622484967754f5848640456 upstream.
The patch is meant to support LARA-R6 Cat 1 module family.
Module USB ID:
Vendor ID: 0x05c6
Product ID: 0x90fA
Interface layout:
If 0: Diagnostic
If 1: AT parser
If 2: AT parser
If 3: QMI wwan (not available in all versions)
--- drivers/usb/serial/option.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/usb/serial/option.c +3 -0
@@ -238,6 +238,7 @@ static void option_instat_callback(struc#define QUECTEL_PRODUCT_UC15 0x9090/* These u-blox products use Qualcomm's vendor ID */ #define UBLOX_PRODUCT_R410M 0x90b2 +#define UBLOX_PRODUCT_R6XX 0x90fa/* These Yuga products use Qualcomm's vendor ID */ #define YUGA_PRODUCT_CLM920_NC5 0x9625
@@ -1101,6 +1102,8 @@ static const struct usb_device_id option/* u-blox products using Qualcomm vendor ID */ { USB_DEVICE(QUALCOMM_VENDOR_ID, UBLOX_PRODUCT_R410M), .driver_info = RSVD(1) | RSVD(3) }, + { USB_DEVICE(QUALCOMM_VENDOR_ID, UBLOX_PRODUCT_R6XX), + .driver_info = RSVD(3) }, /* Quectel products using Quectel vendor ID */ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC21, 0xff, 0xff, 0xff), .driver_info = NUMEP2 },
Greg Kroah-Hartman
maintainerPATCH 167/223 USB: serial: cp210x: fix comments for GE CS1000
In reply to Greg Kroah-HartmanFrom: Ian Ray <[email protected]>
commit e9db418d4b828dd049caaf5ed65dc86f93bb1a0c upstream.
Fix comments for GE CS1000 CP210x USB ID assignments.
--- drivers/usb/serial/cp210x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/usb/serial/cp210x.c +2 -2
@@ -202,8 +202,8 @@ static const struct usb_device_id id_tab { USB_DEVICE(0x1901, 0x0194) }, /* GE Healthcare Remote Alarm Box */ { USB_DEVICE(0x1901, 0x0195) }, /* GE B850/B650/B450 CP2104 DP UART interface */ { USB_DEVICE(0x1901, 0x0196) }, /* GE B850 CP2105 DP UART interface */ - { USB_DEVICE(0x1901, 0x0197) }, /* GE CS1000 Display serial interface */ - { USB_DEVICE(0x1901, 0x0198) }, /* GE CS1000 M.2 Key E serial interface */ + { USB_DEVICE(0x1901, 0x0197) }, /* GE CS1000 M.2 Key E serial interface */ + { USB_DEVICE(0x1901, 0x0198) }, /* GE CS1000 Display serial interface */ { USB_DEVICE(0x199B, 0xBA30) }, /* LORD WSDA-200-USB */ { USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */ { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
Greg Kroah-Hartman
maintainerPATCH 168/223 USB: serial: cp210x: add ID for CEL EM3588 USB ZigBee stick
In reply to Greg Kroah-HartmanFrom: John Keeping <[email protected]>
commit d6a206e60124a9759dd7f6dfb86b0e1d3b1df82e upstream.
Add the USB serial device ID for the CEL ZigBee EM3588 radio stick.
--- drivers/usb/serial/cp210x.c | 1 + 1 file changed, 1 insertion(+)
drivers/usb/serial/cp210x.c +1 -0
@@ -155,6 +155,7 @@ static const struct usb_device_id id_tab { USB_DEVICE(0x10C4, 0x89A4) }, /* CESINEL FTBC Flexible Thyristor Bridge Controller */ { USB_DEVICE(0x10C4, 0x89FB) }, /* Qivicon ZigBee USB Radio Stick */ { USB_DEVICE(0x10C4, 0x8A2A) }, /* HubZ dual ZigBee and Z-Wave dongle */ + { USB_DEVICE(0x10C4, 0x8A5B) }, /* CEL EM3588 ZigBee USB Stick */ { USB_DEVICE(0x10C4, 0x8A5E) }, /* CEL EM3588 ZigBee USB Stick Long Range */ { USB_DEVICE(0x10C4, 0x8B34) }, /* Qivicon ZigBee USB Radio Stick */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
Greg Kroah-Hartman
maintainerPATCH 169/223 usb: gadget: Fix Unbalanced pm_runtime_enable in tegra_xudc_probe
In reply to Greg Kroah-HartmanFrom: Zhang Qilong <[email protected]>
commit 5b01248156bd75303e66985c351dee648c149979 upstream.
Add missing pm_runtime_disable() when probe error out. It could avoid pm_runtime implementation complains when removing and probing again the driver.
--- drivers/usb/gadget/udc/tegra-xudc.c | 1 + 1 file changed, 1 insertion(+)
drivers/usb/gadget/udc/tegra-xudc.c +1 -0
@@ -3861,6 +3861,7 @@ static int tegra_xudc_probe(struct platfreturn 0 ; free_eps: +pm_runtime_disable (&pdev->dev);tegra_xudc_free_eps (xudc); free_event_ring:tegra_xudc_free_event_ring (xudc);
Greg Kroah-Hartman
maintainerPATCH 170/223 usb: dwc2: Skip clock gating on Samsung SoCs
In reply to Greg Kroah-HartmanFrom: Marek Szyprowski <[email protected]>
commit c4a0f7a6ab5417eb6105b0e1d7e6e67f6ef7d4e5 upstream.
Commit 0112b7ce68ea ("usb: dwc2: Update dwc2_handle_usb_suspend_intr function.") changed the way the driver handles power down modes in a such way that it uses clock gating when no other power down mode is available.
This however doesn't work well on the DWC2 implementation used on the Samsung SoCs. When a clock gating is enabled, system hangs. It looks that the proper clock gating requires some additional glue code in the shared USB2 PHY and/or Samsung glue code for the DWC2. To restore driver operation on the Samsung SoCs simply skip enabling clock gating mode until one finds what is really needed to make it working reliably.
--- drivers/usb/dwc2/core.h | 4 ++++ drivers/usb/dwc2/core_intr.c | 3 ++- drivers/usb/dwc2/hcd.c | 6 ++++-- drivers/usb/dwc2/params.c | 1 + 4 files changed, 11 insertions(+), 3 deletions(-)
drivers/usb/dwc2/core.h +4 -0
@@ -383,6 +383,9 @@ enum dwc2_ep0_state {* 0 - No (default) * 1 - Partial power down * 2 - Hibernation +* @no_clock_gating: Specifies whether to avoid clock gating feature. +* 0 - No (use clock gating) +* 1 - Yes (avoid it) * @lpm: Enable LPM support. * 0 - No * 1 - Yes
@@ -480,6 +483,7 @@ struct dwc2_core_params {#define DWC2_POWER_DOWN_PARAM_NONE 0#define DWC2_POWER_DOWN_PARAM_PARTIAL 1#define DWC2_POWER_DOWN_PARAM_HIBERNATION 2 +bool no_clock_gating;bool lpm;bool lpm_clock_gating;
drivers/usb/dwc2/core_intr.c +2 -1
@@ -556,7 +556,8 @@ static void dwc2_handle_usb_suspend_intr* If neither hibernation nor partial power down are supported, * clock gating is used to save power. */ -dwc2_gadget_enter_clock_gating (hsotg); +if (!hsotg->params.no_clock_gating) +dwc2_gadget_enter_clock_gating (hsotg); }/*
drivers/usb/dwc2/hcd.c +4 -2
@@ -3338,7 +3338,8 @@ int dwc2_port_suspend(struct dwc2_hsotg* If not hibernation nor partial power down are supported, * clock gating is used to save power. */ -dwc2_host_enter_clock_gating (hsotg); +if (!hsotg->params.no_clock_gating) +dwc2_host_enter_clock_gating (hsotg);break ; }
@@ -4402,7 +4403,8 @@ static int _dwc2_hcd_suspend(struct usb_* If not hibernation nor partial power down are supported, * clock gating is used to save power. */ -dwc2_host_enter_clock_gating (hsotg); +if (!hsotg->params.no_clock_gating) +dwc2_host_enter_clock_gating (hsotg);/* After entering suspend, hardware is not accessible */ clear_bit (HCD_FLAG_HW_ACCESSIBLE , &hcd->flags);
drivers/usb/dwc2/params.c +1 -0
@@ -76,6 +76,7 @@ static void dwc2_set_s3c6400_params(strustruct dwc2_core_params *p = &hsotg->params; p->power_down =DWC2_POWER_DOWN_PARAM_NONE ; + p->no_clock_gating = true; p->phy_utmi_width =8 ; }
Greg Kroah-Hartman
maintainerPATCH 171/223 usb: dwc2: gadget: Fix GOUTNAK flow for Slave mode.
In reply to Greg Kroah-HartmanFrom: Minas Harutyunyan <[email protected]>
commit fecb3a171db425e5068b27231f8efe154bf72637 upstream.
Because of dwc2_hsotg_ep_stop_xfr() function uses poll mode, first need to mask GINTSTS_GOUTNAKEFF interrupt. In Slave mode GINTSTS_GOUTNAKEFF interrupt will be aserted only after pop OUT NAK status packet from RxFIFO.
In dwc2_hsotg_ep_sethalt() function before setting DCTL_SGOUTNAK need to unmask GOUTNAKEFF interrupt.
Tested by USBCV CH9 and MSC tests set in Slave, BDMA and DDMA. All tests are passed.
--- drivers/usb/dwc2/gadget.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)
drivers/usb/dwc2/gadget.c +21 -0
@@ -3900,9 +3900,27 @@ static void dwc2_hsotg_ep_stop_xfr(struc __func__); } }else { +/* Mask GINTSTS_GOUTNAKEFF interrupt */ +dwc2_hsotg_disable_gsint (hsotg,GINTSTS_GOUTNAKEFF ); +if (!(dwc2_readl (hsotg,GINTSTS ) &GINTSTS_GOUTNAKEFF ))dwc2_set_bit (hsotg,DCTL ,DCTL_SGOUTNAK ); +if (!using_dma (hsotg)) { +/* Wait for GINTSTS_RXFLVL interrupt */ +if (dwc2_hsotg_wait_bit_set (hsotg,GINTSTS , +GINTSTS_RXFLVL ,100 )) { +dev_warn (hsotg->dev,"%s: timeout GINTSTS.RXFLVL\n" , + __func__); + }else { +/* +* Pop GLOBAL OUT NAK status packet from RxFIFO +* to assert GOUTNAKEFF interrupt +*/ +dwc2_readl (hsotg,GRXSTSP ); + } + } +/* Wait for global nak to take effect */ if (dwc2_hsotg_wait_bit_set (hsotg,GINTSTS ,GINTSTS_GOUTNAKEFF ,100 ))
@@ -4348,6 +4366,9 @@ static int dwc2_hsotg_ep_sethalt(struct epctl =dwc2_readl (hs, epreg);if (value) { +/* Unmask GOUTNAKEFF interrupt */ +dwc2_hsotg_en_gsint (hs,GINTSTS_GOUTNAKEFF ); +if (!(dwc2_readl (hs,GINTSTS ) &GINTSTS_GOUTNAKEFF ))dwc2_set_bit (hs,DCTL ,DCTL_SGOUTNAK );// STALL bit will be set in GOUTNAKEFF interrupt handler
Greg Kroah-Hartman
maintainerPATCH 172/223 usb: dwc2: gadget: Fix sending zero length packet in DDMA mode.
In reply to Greg Kroah-HartmanFrom: Minas Harutyunyan <[email protected]>
commit d53dc38857f6dbefabd9eecfcbf67b6eac9a1ef4 upstream.
Sending zero length packet in DDMA mode perform by DMA descriptor by setting SP (short packet) flag.
For DDMA in function dwc2_hsotg_complete_in() does not need to send zlp.
Tested by USBCV MSC tests.
--- drivers/usb/dwc2/gadget.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/usb/dwc2/gadget.c +6 -4
@@ -2749,12 +2749,14 @@ static void dwc2_hsotg_complete_in(strucreturn ; } -/* Zlp for all endpoints, for ep0 only in DATA IN stage */ +/* Zlp for all endpoints in non DDMA, for ep0 only in DATA IN stage */ if (hs_ep->send_zlp) { -dwc2_hsotg_program_zlp (hsotg, hs_ep); hs_ep->send_zlp =0 ; -/* transfer will be completed on next complete interrupt */ -return ; +if (!using_desc_dma (hsotg)) { +dwc2_hsotg_program_zlp (hsotg, hs_ep); +/* transfer will be completed on next complete interrupt */ +return ; + } }if (hs_ep->index ==0 && hsotg->ep0_state ==DWC2_EP0_DATA_IN ) {
Greg Kroah-Hartman
maintainerPATCH 173/223 usb: typec: tipd: Dont block probing of consumer of "connector" nodes
In reply to Greg Kroah-HartmanFrom: Martin Kepplinger <[email protected]>
commit 57560ee95cb7f91cf0bc31d4ae8276e0dcfe17aa upstream.
Similar as with tcpm this patch lets fw_devlink know not to wait on the fwnode to be populated as a struct device.
Without this patch, USB functionality can be broken on some previously supported boards.
--- drivers/usb/typec/tipd/core.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/usb/typec/tipd/core.c +9 -0
@@ -629,6 +629,15 @@ static int tps6598x_probe(struct i2c_cliif (!fwnode)return -ENODEV ; +/* +* This fwnode has a "compatible" property, but is never populated as a +* struct device. Instead we simply parse it to read the properties. +* This breaks fw_devlink=on. To maintain backward compatibility +* with existing DT files, we work around this by deleting any +* fwnode_links to/from this fwnode. +*/ +fw_devlink_purge_absent_suppliers (fwnode); + tps->role_sw =fwnode_usb_role_switch_get (fwnode);if (IS_ERR (tps->role_sw)) { ret =PTR_ERR (tps->role_sw);
Greg Kroah-Hartman
maintainerPATCH 174/223 usb: typec: stusb160x: register role switch before interrupt registration
In reply to Greg Kroah-HartmanFrom: Amelie Delaunay <[email protected]>
commit 86762ad4abcc549deb7a155c8e5e961b9755bcf0 upstream.
During interrupt registration, attach state is checked. If attached, then the Type-C state is updated with typec_set_xxx functions and role switch is set with usb_role_switch_set_role().
If the usb_role_switch parameter is error or null, the function simply returns 0.
So, to update usb_role_switch role if a device is attached before the irq is registered, usb_role_switch must be registered before irq registration.
--- drivers/usb/typec/stusb160x.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
drivers/usb/typec/stusb160x.c +7 -4
@@ -739,10 +739,6 @@ static int stusb160x_probe(struct i2c_cltypec_set_pwr_opmode (chip->port, chip->pwr_opmode);if (client->irq) { - ret =stusb160x_irq_init (chip, client->irq); -if (ret) - goto port_unregister; - chip->role_sw =fwnode_usb_role_switch_get (fwnode);if (IS_ERR (chip->role_sw)) { ret =PTR_ERR (chip->role_sw);
@@ -752,6 +748,10 @@ static int stusb160x_probe(struct i2c_cl ret); goto port_unregister; } + + ret =stusb160x_irq_init (chip, client->irq); +if (ret) + goto role_sw_put; }else {/* * If Source or Dual power role, need to enable VDD supply
@@ -775,6 +775,9 @@ static int stusb160x_probe(struct i2c_clreturn 0 ; +role_sw_put: +if (chip->role_sw) +usb_role_switch_put (chip->role_sw); port_unregister:typec_unregister_port (chip->port); all_reg_disable:
Greg Kroah-Hartman
maintainerPATCH 175/223 usb: typec: stusb160x: Dont block probing of consumer of "connector" nodes
In reply to Greg Kroah-HartmanFrom: Amelie Delaunay <[email protected]>
commit 6b63376722d9e1b915a2948e9b30f4ba2712e3f5 upstream.
Similar as with tcpm this patch lets fw_devlink know not to wait on the fwnode to be populated as a struct device.
Without this patch, USB functionality can be broken on some previously supported boards.
--- drivers/usb/typec/stusb160x.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/usb/typec/stusb160x.c +9 -0
@@ -686,6 +686,15 @@ static int stusb160x_probe(struct i2c_clreturn -ENODEV ;/* +* This fwnode has a "compatible" property, but is never populated as a +* struct device. Instead we simply parse it to read the properties. +* This it breaks fw_devlink=on. To maintain backward compatibility +* with existing DT files, we work around this by deleting any +* fwnode_links to/from this fwnode. +*/ +fw_devlink_purge_absent_suppliers (fwnode); + +/* * When both VDD and VSYS power supplies are present, the low power * supply VSYS is selected when VSYS voltage is above 3.1 V. * Otherwise VDD is selected.
Greg Kroah-Hartman
maintainerPATCH 176/223 firmware/efi: Tell memblock about EFI iomem reservations
In reply to Greg Kroah-HartmanFrom: Marc Zyngier <[email protected]>
commit 2bab693a608bdf614b9fcd44083c5100f34b9f77 upstream.
kexec_load_file() relies on the memblock infrastructure to avoid stamping over regions of memory that are essential to the survival of the system.
However, nobody seems to agree how to flag these regions as reserved, and (for example) EFI only publishes its reservations in /proc/iomem for the benefit of the traditional, userspace based kexec tool.
On arm64 platforms with GICv3, this can result in the payload being placed at the location of the LPI tables. Shock, horror!
Let's augment the EFI reservation code with a memblock_reserve() call, protecting our dear tables from the secondary kernel invasion.
--- drivers/firmware/efi/efi.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
drivers/firmware/efi/efi.c +12 -1
@@ -896,6 +896,7 @@ static int __init efi_memreserve_map_roostatic int efi_mem_reserve_iomem (phys_addr_t addr,u64 size) {struct resource *res, *parent; +int ret; res =kzalloc (sizeof (struct resource ),GFP_ATOMIC );if (!res)
@@ -908,7 +909,17 @@ static int efi_mem_reserve_iomem(phys_ad/* we expect a conflict with a 'System RAM' region */ parent =request_resource_conflict (&iomem_resource, res); -return parent ?request_resource (parent, res) :0 ; + ret = parent ?request_resource (parent, res) :0 ; + +/* +* Given that efi_mem_reserve_iomem() can be called at any +* time, only call memblock_reserve() if the architecture +* keeps the infrastructure around. +*/ +if (IS_ENABLED (CONFIG_ARCH_KEEP_MEMBLOCK ) && !ret) +memblock_reserve (addr, size); + +return ret; }int __ref efi_mem_reserve_persistent (phys_addr_t addr,u64 size)
Greg Kroah-Hartman
maintainerPATCH 177/223 tracepoints: Update static_call before tp_funcs when adding a tracepoint
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (VMware) <[email protected]>
commit 352384d5c84ebe40fa77098cc234fe173247d8ef upstream.
Because of the significant overhead that retpolines pose on indirect calls, the tracepoint code was updated to use the new "static_calls" that can modify the running code to directly call a function instead of using an indirect caller, and this function can be changed at runtime.
In the tracepoint code that calls all the registered callbacks that are attached to a tracepoint, the following is done:
it_func_ptr = rcu_dereference_raw((&__tracepoint_##name)->funcs);
if (it_func_ptr) {
__data = (it_func_ptr)->data;
static_call(tp_func_##name)(__data, args);
}If there's just a single callback, the static_call is updated to just call that callback directly. Once another handler is added, then the static caller is updated to call the iterator, that simply loops over all the funcs in the array and calls each of the callbacks like the old method using indirect calling.
The issue was discovered with a race between updating the funcs array and updating the static_call. The funcs array was updated first and then the static_call was updated. This is not an issue as long as the first element in the old array is the same as the first element in the new array. But that assumption is incorrect, because callbacks also have a priority field, and if there's a callback added that has a higher priority than the callback on the old array, then it will become the first callback in the new array. This means that it is possible to call the old callback with the new callback data element, which can cause a kernel panic.
static_call = callback1()
funcs[] = {callback1,data1};
callback2 has higher priority than callback1
CPU 1 CPU 2
----- ----- new_funcs = {callback2,data2},
{callback1,data1}rcu_assign_pointer(tp->funcs, new_funcs);
/*
* Now tp->funcs has the new array
* but the static_call still calls callback1
*/
it_func_ptr = tp->funcs [ new_funcs ] data = it_func_ptr->data [ data2 ] static_call(callback1, data); /* Now callback1 is called with * callback2's data */ [ KERNEL PANIC ]
update_static_call(iterator);
To prevent this from happening, always switch the static_call to the iterator before assigning the tp->funcs to the new array. The iterator will always properly match the callback with its data.
To trigger this bug:
In one terminal:
while :; do hackbench 50; done
In another terminal
echo 1 > /sys/kernel/tracing/events/sched/sched_waking/enable
while :; do
echo 1 > /sys/kernel/tracing/set_event_pid;
sleep 0.5
echo 0 > /sys/kernel/tracing/set_event_pid;
sleep 0.5done
And it doesn't take long to crash. This is because the set_event_pid adds a callback to the sched_waking tracepoint with a high priority, which will be called before the sched_waking trace event callback is called.
Note, the removal to a single callback updates the array first, before changing the static_call to single callback, which is the proper order as the first element in the array is the same as what the static_call is being changed to.
--- kernel/tracepoint.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/tracepoint.c +1 -1
@@ -299,8 +299,8 @@ static int tracepoint_add_func(struct tr* a pointer to it. This array is referenced by __DO_TRACE from * include/linux/tracepoint.h using rcu_dereference_sched(). */ -rcu_assign_pointer (tp->funcs, tp_funcs);tracepoint_update_call (tp, tp_funcs, false); +rcu_assign_pointer (tp->funcs, tp_funcs);static_key_enable (&tp->key);release_probes (old);
Greg Kroah-Hartman
maintainerPATCH 178/223 tracing/histogram: Rename "cpu" to "common_cpu"
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (VMware) <[email protected]>
commit 1e3bac71c5053c99d438771fc9fa5082ae5d90aa upstream.
Currently the histogram logic allows the user to write "cpu" in as an event field, and it will record the CPU that the event happened on.
The problem with this is that there's a lot of events that have "cpu" as a real field, and using "cpu" as the CPU it ran on, makes it impossible to run histograms on the "cpu" field of events.
For example, if I want to have a histogram on the count of the workqueue_queue_work event on its cpu field, running:
Quoted 1 line
# echo 'hist:keys=cpu' > events/workqueue/workqueue_queue_work/trigger
Gives a misleading and wrong result.
Change the command to "common_cpu" as no event should have "common_*" fields as that's a reserved name for fields used by all events. And this makes sense here as common_cpu would be a field used by all events.
Now we can even do:
Quoted 2 lines
# echo 'hist:keys=common_cpu,cpu if cpu < 100' > events/workqueue/workqueue_queue_work/trigger # cat events/workqueue/workqueue_queue_work/hist
# event histogram # # trigger info: hist:keys=common_cpu,cpu:vals=hitcount:sort=hitcount:size=2048 if cpu < 100 [active] #
{ common_cpu: 0, cpu: 2 } hitcount: 1
{ common_cpu: 0, cpu: 4 } hitcount: 1
{ common_cpu: 7, cpu: 7 } hitcount: 1
{ common_cpu: 0, cpu: 7 } hitcount: 1
{ common_cpu: 0, cpu: 1 } hitcount: 1
{ common_cpu: 0, cpu: 6 } hitcount: 2
{ common_cpu: 0, cpu: 5 } hitcount: 2
{ common_cpu: 1, cpu: 1 } hitcount: 4
{ common_cpu: 6, cpu: 6 } hitcount: 4
{ common_cpu: 5, cpu: 5 } hitcount: 14
{ common_cpu: 4, cpu: 4 } hitcount: 26
{ common_cpu: 0, cpu: 0 } hitcount: 39
{ common_cpu: 2, cpu: 2 } hitcount: 184Now for backward compatibility, I added a trick. If "cpu" is used, and the field is not found, it will fall back to "common_cpu" and work as it did before. This way, it will still work for old programs that use "cpu" to get the actual CPU, but if the event has a "cpu" as a field, it will get that event's "cpu" field, which is probably what it wants anyway.
I updated the tracefs/README to include documentation about both the common_timestamp and the common_cpu. This way, if that text is present in the README, then an application can know that common_cpu is supported over just plain "cpu".
--- Documentation/trace/histogram.rst | 2 +- kernel/trace/trace.c | 4 ++++ kernel/trace/trace_events_hist.c | 22 ++++++++++++++++------ 3 files changed, 21 insertions(+), 7 deletions(-)
Documentation/trace/histogram.rst +1 -1
@@ -191,7 +191,7 @@ Documentation written by Tom Zanussi with the event, in nanoseconds. May be modified by .usecs to have timestamps interpreted as microseconds. - cpu int the cpu on which the event occurred. + common_cpu int the cpu on which the event occurred. ====================== ==== ======================================= Extended error information
kernel/trace/trace.c +4 -0
@@ -5565,6 +5565,10 @@ static const char readme_msg[] ="\t [:name=histname1]\n" "\t [:<handler>.<action>]\n" "\t [if <filter>]\n\n" +"\t Note, special fields can be used as well:\n" +"\t common_timestamp - to record current timestamp\n" +"\t common_cpu - to record the CPU the event happened on\n" +"\n" "\t When a matching event is hit, an entry is added to a hash\n" "\t table using the key(s) and value(s) named, and the value of a\n" "\t sum called 'hitcount' is incremented. Keys and values\n"
kernel/trace/trace_events_hist.c +16 -6
@@ -1111,7 +1111,7 @@ static const char *hist_field_name(struc field->flags & HIST_FIELD_FL_ALIAS) field_name =hist_field_name (field->operands[0 ], ++level); else if (field->flags & HIST_FIELD_FL_CPU) - field_name ="cpu" ; + field_name ="common_cpu" ; else if (field->flags & HIST_FIELD_FL_EXPR || field->flags & HIST_FIELD_FL_VAR_REF) {if (field->system) {
@@ -1991,14 +1991,24 @@ parse_field(struct hist_trigger_data *hi hist_data->enable_timestamps = true;if (*flags &HIST_FIELD_FL_TIMESTAMP_USECS ) hist_data->attrs->ts_in_usecs = true; - }else if (strcmp (field_name,"cpu" ) ==0 ) + }else if (strcmp (field_name,"common_cpu" ) ==0 ) *flags |=HIST_FIELD_FL_CPU ;else { field =trace_find_event_field (file->event_call, field_name);if (!field || !field->size) { -hist_err (tr,HIST_ERR_FIELD_NOT_FOUND ,errpos (field_name)); - field =ERR_PTR (-EINVAL ); - goto out; +/* +* For backward compatibility, if field_name +* was "cpu", then we treat this the same as +* common_cpu. +*/ +if (strcmp (field_name,"cpu" ) ==0 ) { + *flags |=HIST_FIELD_FL_CPU ; + }else { +hist_err (tr,HIST_ERR_FIELD_NOT_FOUND , +errpos (field_name)); + field =ERR_PTR (-EINVAL ); + goto out; + } } } out:
@@ -5085,7 +5095,7 @@ static void hist_field_print(struct seq_seq_printf (m,"%s=" , hist_field->var.name);if (hist_field->flags &HIST_FIELD_FL_CPU ) -seq_puts (m,"cpu" ); +seq_puts (m,"common_cpu" );else if (field_name) {if (hist_field->flags &HIST_FIELD_FL_VAR_REF || hist_field->flags &HIST_FIELD_FL_ALIAS )
Greg Kroah-Hartman
maintainerPATCH 179/223 tracing: Fix bug in rb_per_cpu_empty() that might cause deadloop.
In reply to Greg Kroah-HartmanFrom: Haoran Luo <[email protected]>
commit 67f0d6d9883c13174669f88adac4f0ee656cc16a upstream.
The "rb_per_cpu_empty()" misinterpret the condition (as not-empty) when "head_page" and "commit_page" of "struct ring_buffer_per_cpu" points to the same buffer page, whose "buffer_data_page" is empty and "read" field is non-zero.
An error scenario could be constructed as followed (kernel perspective):
1. All pages in the buffer has been accessed by reader(s) so that all of them will have non-zero "read" field.
2. Read and clear all buffer pages so that "rb_num_of_entries()" will return 0 rendering there's no more data to read. It is also required that the "read_page", "commit_page" and "tail_page" points to the same page, while "head_page" is the next page of them.
3. Invoke "ring_buffer_lock_reserve()" with large enough "length" so that it shot pass the end of current tail buffer page. Now the "head_page", "commit_page" and "tail_page" points to the same page.
4. Discard current event with "ring_buffer_discard_commit()", so that "head_page", "commit_page" and "tail_page" points to a page whose buffer data page is now empty.
When the error scenario has been constructed, "tracing_read_pipe" will be trapped inside a deadloop: "trace_empty()" returns 0 since "rb_per_cpu_empty()" returns 0 when it hits the CPU containing such constructed ring buffer. Then "trace_find_next_entry_inc()" always return NULL since "rb_num_of_entries()" reports there's no more entry to read. Finally "trace_seq_to_user()" returns "-EBUSY" spanking "tracing_read_pipe" back to the start of the "waitagain" loop.
I've also written a proof-of-concept script to construct the scenario and trigger the bug automatically, you can use it to trace and validate my reasoning above:
https://github.com/aegistudio/RingBufferDetonator.git
Tests has been carried out on linux kernel 5.14-rc2 (2734d6c1b1a089fb593ef6a23d4b70903526fe0c), my fixed version of kernel (for testing whether my update fixes the bug) and some older kernels (for range of affected kernels). Test result is also attached to the proof-of-concept repository.
--- kernel/trace/ring_buffer.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-)
kernel/trace/ring_buffer.c +24 -4
@@ -3880,10 +3880,30 @@ static bool rb_per_cpu_empty(struct ringif (unlikely (!head))return true; -return reader->read ==rb_page_commit (reader) && - (commit == reader || - (commit == head && - head->read ==rb_page_commit (commit))); +/* Reader should exhaust content in reader page */ +if (reader->read !=rb_page_commit (reader)) +return false; + +/* +* If writers are committing on the reader page, knowing all +* committed content has been read, the ring buffer is empty. +*/ +if (commit == reader) +return true; + +/* +* If writers are committing on a page other than reader page +* and head page, there should always be content to read. +*/ +if (commit != head) +return false; + +/* +* Writers are committing on the head page, we just need +* to care about there're committed data, and the reader will +* swap reader page with head page when it is to read data. +*/ +return rb_page_commit (commit) ==0 ; }/**
Greg Kroah-Hartman
maintainerPATCH 180/223 tracing: Synthetic event field_pos is an index not a boolean
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (VMware) <[email protected]>
commit 3b13911a2fd0dd0146c9777a254840c5466cf120 upstream.
Performing the following:
Quoted 3 lines
# echo 'wakeup_lat s32 pid; u64 delta; char wake_comm[]' > synthetic_events # echo 'hist:keys=pid:__arg__1=common_timestamp.usecs' > events/sched/sched_waking/trigger # echo 'hist:keys=next_pid:pid=next_pid,delta=common_timestamp.usecs-$__arg__1:onmatch(sched.sched_waking).trace(wakeup_lat,$pid,$delta,prev_comm)'\
> events/sched/sched_switch/trigger
Quoted 1 line
# echo 1 > events/synthetic/enable
Crashed the kernel:
BUG: kernel NULL pointer dereference, address: 000000000000001b #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 0 P4D 0 Oops: 0000 [#1] PREEMPT SMP CPU: 7 PID: 0 Comm: swapper/7 Not tainted 5.13.0-rc5-test+ #104 Hardware name: Hewlett-Packard HP Compaq Pro 6300 SFF/339A, BIOS K01 v03.03 07/14/2016 RIP: 0010:strlen+0x0/0x20 Code: f6 82 80 2b 0b bc 20 74 11 0f b6 50 01 48 83 c0 01 f6 82 80 2b 0b bc 20 75 ef c3 66 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 <80> 3f 00 74 10 48 89 f8 48 83 c0 01 80 38 9 f8 c3 31 RSP: 0018:ffffaa75000d79d0 EFLAGS: 00010046 RAX: 0000000000000002 RBX: ffff9cdb55575270 RCX: 0000000000000000 RDX: ffff9cdb58c7a320 RSI: ffffaa75000d7b40 RDI: 000000000000001b RBP: ffffaa75000d7b40 R08: ffff9cdb40a4f010 R09: ffffaa75000d7ab8 R10: ffff9cdb4398c700 R11: 0000000000000008 R12: ffff9cdb58c7a320 R13: ffff9cdb55575270 R14: ffff9cdb58c7a000 R15: 0000000000000018 FS: 0000000000000000(0000) GS:ffff9cdb5aa00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000000000000001b CR3: 00000000c0612006 CR4: 00000000001706e0 Call Trace: trace_event_raw_event_synth+0x90/0x1d0 action_trace+0x5b/0x70 event_hist_trigger+0x4bd/0x4e0 ? cpumask_next_and+0x20/0x30 ? update_sd_lb_stats.constprop.0+0xf6/0x840 ? __lock_acquire.constprop.0+0x125/0x550 ? find_held_lock+0x32/0x90 ? sched_clock_cpu+0xe/0xd0 ? lock_release+0x155/0x440 ? update_load_avg+0x8c/0x6f0 ? enqueue_entity+0x18a/0x920 ? __rb_reserve_next+0xe5/0x460 ? ring_buffer_lock_reserve+0x12a/0x3f0 event_triggers_call+0x52/0xe0 trace_event_buffer_commit+0x1ae/0x240 trace_event_raw_event_sched_switch+0x114/0x170 __traceiter_sched_switch+0x39/0x50 __schedule+0x431/0xb00 schedule_idle+0x28/0x40 do_idle+0x198/0x2e0 cpu_startup_entry+0x19/0x20 secondary_startup_64_no_verify+0xc2/0xcb
The reason is that the dynamic events array keeps track of the field position of the fields array, via the field_pos variable in the synth_field structure. Unfortunately, that field is a boolean for some reason, which means any field_pos greater than 1 will be a bug (in this case it was 2).
--- kernel/trace/trace_synth.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/trace/trace_synth.h +1 -1
@@ -14,10 +14,10 @@ struct synth_field {char *name;size_t size;unsigned int offset; +unsigned int field_pos;bool is_signed;bool is_string;bool is_dynamic; -bool field_pos; };struct synth_event {
Greg Kroah-Hartman
maintainerPATCH 181/223 btrfs: check for missing device in btrfs_trim_fs
In reply to Greg Kroah-HartmanFrom: Anand Jain <[email protected]>
commit 16a200f66ede3f9afa2e51d90ade017aaa18d213 upstream.
A fstrim on a degraded raid1 can trigger the following null pointer dereference:
BTRFS info (device loop0): allowing degraded mounts
BTRFS info (device loop0): disk space caching is enabled
BTRFS info (device loop0): has skinny extents
BTRFS warning (device loop0): devid 2 uuid 97ac16f7-e14d-4db1-95bc-3d489b424adb is missing BTRFS warning (device loop0): devid 2 uuid 97ac16f7-e14d-4db1-95bc-3d489b424adb is missing BTRFS info (device loop0): enabling ssd optimizations
BUG: kernel NULL pointer dereference, address: 0000000000000620 PGD 0 P4D 0 Oops: 0000 [#1] SMP NOPTI CPU: 0 PID: 4574 Comm: fstrim Not tainted 5.13.0-rc7+ #31 Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 RIP: 0010:btrfs_trim_fs+0x199/0x4a0 [btrfs] RSP: 0018:ffff959541797d28 EFLAGS: 00010293 RAX: 0000000000000000 RBX: ffff946f84eca508 RCX: a7a67937adff8608 RDX: ffff946e8122d000 RSI: 0000000000000000 RDI: ffffffffc02fdbf0 RBP: ffff946ea4615000 R08: 0000000000000001 R09: 0000000000000000 R10: 0000000000000000 R11: ffff946e8122d960 R12: 0000000000000000 R13: ffff959541797db8 R14: ffff946e8122d000 R15: ffff959541797db8 FS: 00007f55917a5080(0000) GS:ffff946f9bc00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000620 CR3: 000000002d2c8001 CR4: 00000000000706f0 Call Trace: btrfs_ioctl_fitrim+0x167/0x260 [btrfs] btrfs_ioctl+0x1c00/0x2fe0 [btrfs] ? selinux_file_ioctl+0x140/0x240 ? syscall_trace_enter.constprop.0+0x188/0x240 ? __x64_sys_ioctl+0x83/0xb0 __x64_sys_ioctl+0x83/0xb0
Reproducer:
$ mkfs.btrfs -fq -d raid1 -m raid1 /dev/loop0 /dev/loop1 $ mount /dev/loop0 /btrfs $ umount /btrfs $ btrfs dev scan --forget $ mount -o degraded /dev/loop0 /btrfs
$ fstrim /btrfs
The reason is we call btrfs_trim_free_extents() for the missing device, which uses device->bdev (NULL for missing device) to find if the device supports discard.
Fix is to check if the device is missing before calling btrfs_trim_free_extents().
--- fs/btrfs/extent-tree.c | 3 +++ 1 file changed, 3 insertions(+)
fs/btrfs/extent-tree.c +3 -0
@@ -6034,6 +6034,9 @@ int btrfs_trim_fs(struct btrfs_fs_info *mutex_lock (&fs_info->fs_devices->device_list_mutex); devices = &fs_info->fs_devices->devices;list_for_each_entry (device, devices, dev_list) { +if (test_bit (BTRFS_DEV_STATE_MISSING , &device->dev_state)) +continue ; + ret =btrfs_trim_free_extents (device, &group_trimmed);if (ret) { dev_failed++;
Greg Kroah-Hartman
maintainerPATCH 182/223 btrfs: fix unpersisted i_size on fsync after expanding truncate
In reply to Greg Kroah-HartmanFrom: Filipe Manana <[email protected]>
commit 9acc8103ab594f72250788cb45a43427f36d685d upstream.
If we have an inode that does not have the full sync flag set, was changed in the current transaction, then it is logged while logging some other inode (like its parent directory for example), its i_size is increased by a truncate operation, the log is synced through an fsync of some other inode and then finally we explicitly call fsync on our inode, the new i_size is not persisted.
The following example shows how to trigger it, with comments explaining how and why the issue happens:
$ mkfs.btrfs -f /dev/sdc $ mount /dev/sdc /mnt
$ touch /mnt/foo $ xfs_io -f -c "pwrite -S 0xab 0 1M" /mnt/bar
$ sync
# Fsync bar, this will be a noop since the file has not yet been
# modified in the current transaction. The goal here is to clear # BTRFS_INODE_NEEDS_FULL_SYNC from the inode's runtime flags. $ xfs_io -c "fsync" /mnt/bar
# Now rename both files, without changing their parent directory.
$ mv /mnt/bar /mnt/bar2 $ mv /mnt/foo /mnt/foo2
# Increase the size of bar2 with a truncate operation.
$ xfs_io -c "truncate 2M" /mnt/bar2
# Now fsync foo2, this results in logging its parent inode (the root # directory), and logging the parent results in logging the inode of
# file bar2 (its inode item and the new name). The inode of file bar2 # is logged with an i_size of 0 bytes since it's logged in # LOG_INODE_EXISTS mode, meaning we are only logging its names (and # xattrs if it had any) and the i_size of the inode will not be changed # when the log is replayed. $ xfs_io -c "fsync" /mnt/foo2
# Now explicitly fsync bar2. This resulted in doing nothing, not
# logging the inode with the new i_size of 2M and the hole from file # offset 1M to 2M. Because the inode did not have the flag # BTRFS_INODE_NEEDS_FULL_SYNC set, when it was logged through the # fsync of file foo2, its last_log_commit field was updated, # resulting in this explicit of file bar2 not doing anything. $ xfs_io -c "fsync" /mnt/bar2
# File bar2 content and size before a power failure.
$ od -A d -t x1 /mnt/bar2 0000000 ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab * 1048576 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 * 2097152
<power failure>
# Mount the filesystem to replay the log.
$ mount /dev/sdc /mnt
# Read the file again, should have the same content and size as before
# the power failure happened, but it doesn't, i_size is still at 1M. $ od -A d -t x1 /mnt/bar2 0000000 ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab * 1048576
This started to happen after commit 209ecbb8585bf6 ("btrfs: remove stale comment and logic from btrfs_inode_in_log()"), since btrfs_inode_in_log() no longer checks if the inode's list of modified extents is not empty. However, checking that list is not the right way to address this case and the check was added long time ago in commit 125c4cf9f37c98 ("Btrfs: set inode's logged_trans/last_log_commit after ranged fsync") for a different purpose, to address consecutive ranged fsyncs.
The reason that checking for the list emptiness makes this test pass is because during an expanding truncate we create an extent map to represent a hole from the old i_size to the new i_size, and add that extent map to the list of modified extents in the inode. However if we are low on available memory and we can not allocate a new extent map, then we don't treat it as an error and just set the full sync flag on the inode, so that the next fsync does not rely on the list of modified extents - so checking for the emptiness of the list to decide if the inode needs to be logged is not reliable, and results in not logging the inode if it was not possible to allocate the extent map for the hole.
Fix this by ensuring that if we are only logging that an inode exists (inode item, names/references and xattrs), we don't update the inode's last_log_commit even if it does not have the full sync runtime flag set.
A test case for fstests follows soon.
--- fs/btrfs/tree-log.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-)
fs/btrfs/tree-log.c +22 -9
@@ -5515,16 +5515,29 @@ log_extents:spin_lock (&inode->lock); inode->logged_trans = trans->transid;/* -* Don't update last_log_commit if we logged that an inode exists -* after it was loaded to memory (full_sync bit set). -* This is to prevent data loss when we do a write to the inode, -* then the inode gets evicted after all delalloc was flushed, -* then we log it exists (due to a rename for example) and then -* fsync it. This last fsync would do nothing (not logging the -* extents previously written). +* Don't update last_log_commit if we logged that an inode exists. +* We do this for two reasons: +* +* 1) We might have had buffered writes to this inode that were +* flushed and had their ordered extents completed in this +* transaction, but we did not previously log the inode with +* LOG_INODE_ALL. Later the inode was evicted and after that +* it was loaded again and this LOG_INODE_EXISTS log operation +* happened. We must make sure that if an explicit fsync against +* the inode is performed later, it logs the new extents, an +* updated inode item, etc, and syncs the log. The same logic +* applies to direct IO writes instead of buffered writes. +* +* 2) When we log the inode with LOG_INODE_EXISTS, its inode item +* is logged with an i_size of 0 or whatever value was logged +* before. If later the i_size of the inode is increased by a +* truncate operation, the log is synced through an fsync of +* some other inode and then finally an explicit fsync against +* this inode is made, we must make sure this fsync logs the +* inode with the new i_size, the hole between old i_size and +* the new i_size, and syncs the log. */ -if (inode_only !=LOG_INODE_EXISTS || - !test_bit (BTRFS_INODE_NEEDS_FULL_SYNC , &inode->runtime_flags)) +if (inode_only !=LOG_INODE_EXISTS ) inode->last_log_commit = inode->last_sub_trans;spin_unlock (&inode->lock); }
Greg Kroah-Hartman
maintainerPATCH 183/223 btrfs: fix lock inversion problem when doing qgroup extent tracing
In reply to Greg Kroah-HartmanFrom: Filipe Manana <[email protected]>
commit 8949b9a114019b03fbd0d03d65b8647cba4feef3 upstream.
At btrfs_qgroup_trace_extent_post() we call btrfs_find_all_roots() with a NULL value as the transaction handle argument, which makes that function take the commit_root_sem semaphore, which is necessary when we don't hold a transaction handle or any other mechanism to prevent a transaction commit from wiping out commit roots.
However btrfs_qgroup_trace_extent_post() can be called in a context where we are holding a write lock on an extent buffer from a subvolume tree, namely from btrfs_truncate_inode_items(), called either during truncate or unlink operations. In this case we end up with a lock inversion problem because the commit_root_sem is a higher level lock, always supposed to be acquired before locking any extent buffer.
Lockdep detects this lock inversion problem since we switched the extent buffer locks from custom locks to semaphores, and when running btrfs/158 from fstests, it reported the following trace:
[ 9057.626435] ======================================================
[ 9057.627541] WARNING: possible circular locking dependency detected
[ 9057.628334] 5.14.0-rc2-btrfs-next-93 #1 Not tainted
[ 9057.628961] ------------------------------------------------------
[ 9057.629867] kworker/u16:4/30781 is trying to acquire lock:
[ 9057.630824] ffff8e2590f58760 (btrfs-tree-00){++++}-{3:3}, at: __btrfs_tree_read_lock+0x24/0x110 [btrfs]
[ 9057.632542]
but task is already holding lock:
[ 9057.633551] ffff8e25582d4b70 (&fs_info->commit_root_sem){++++}-{3:3}, at: iterate_extent_inodes+0x10b/0x280 [btrfs]
[ 9057.635255]
which lock already depends on the new lock.[ 9057.636292]
the existing dependency chain (in reverse order) is:
[ 9057.637240]
-> #1 (&fs_info->commit_root_sem){++++}-{3:3}:
[ 9057.638138] down_read+0x46/0x140
[ 9057.638648] btrfs_find_all_roots+0x41/0x80 [btrfs]
[ 9057.639398] btrfs_qgroup_trace_extent_post+0x37/0x70 [btrfs]
[ 9057.640283] btrfs_add_delayed_data_ref+0x418/0x490 [btrfs]
[ 9057.641114] btrfs_free_extent+0x35/0xb0 [btrfs]
[ 9057.641819] btrfs_truncate_inode_items+0x424/0xf70 [btrfs]
[ 9057.642643] btrfs_evict_inode+0x454/0x4f0 [btrfs]
[ 9057.643418] evict+0xcf/0x1d0
[ 9057.643895] do_unlinkat+0x1e9/0x300
[ 9057.644525] do_syscall_64+0x3b/0xc0
[ 9057.645110] entry_SYSCALL_64_after_hwframe+0x44/0xae
[ 9057.645835]
-> #0 (btrfs-tree-00){++++}-{3:3}:
[ 9057.646600] __lock_acquire+0x130e/0x2210
[ 9057.647248] lock_acquire+0xd7/0x310
[ 9057.647773] down_read_nested+0x4b/0x140
[ 9057.648350] __btrfs_tree_read_lock+0x24/0x110 [btrfs]
[ 9057.649175] btrfs_read_lock_root_node+0x31/0x40 [btrfs]
[ 9057.650010] btrfs_search_slot+0x537/0xc00 [btrfs]
[ 9057.650849] scrub_print_warning_inode+0x89/0x370 [btrfs]
[ 9057.651733] iterate_extent_inodes+0x1e3/0x280 [btrfs]
[ 9057.652501] scrub_print_warning+0x15d/0x2f0 [btrfs]
[ 9057.653264] scrub_handle_errored_block.isra.0+0x135f/0x1640 [btrfs]
[ 9057.654295] scrub_bio_end_io_worker+0x101/0x2e0 [btrfs]
[ 9057.655111] btrfs_work_helper+0xf8/0x400 [btrfs]
[ 9057.655831] process_one_work+0x247/0x5a0
[ 9057.656425] worker_thread+0x55/0x3c0
[ 9057.656993] kthread+0x155/0x180
[ 9057.657494] ret_from_fork+0x22/0x30
[ 9057.658030]
other info that might help us debug this:[ 9057.659064] Possible unsafe locking scenario:
[ 9057.659824] CPU0 CPU1
[ 9057.660402] ---- ----
[ 9057.660988] lock(&fs_info->commit_root_sem);
[ 9057.661581] lock(btrfs-tree-00);
[ 9057.662348] lock(&fs_info->commit_root_sem);
[ 9057.663254] lock(btrfs-tree-00);
[ 9057.663690]
*** DEADLOCK ***[ 9057.664437] 4 locks held by kworker/u16:4/30781:
[ 9057.665023] #0: ffff8e25922a1148 ((wq_completion)btrfs-scrub){+.+.}-{0:0}, at: process_one_work+0x1c7/0x5a0
[ 9057.666260] #1: ffffabb3451ffe70 ((work_completion)(&work->normal_work)){+.+.}-{0:0}, at: process_one_work+0x1c7/0x5a0
[ 9057.667639] #2: ffff8e25922da198 (&ret->mutex){+.+.}-{3:3}, at: scrub_handle_errored_block.isra.0+0x5d2/0x1640 [btrfs]
[ 9057.669017] #3: ffff8e25582d4b70 (&fs_info->commit_root_sem){++++}-{3:3}, at: iterate_extent_inodes+0x10b/0x280 [btrfs]
[ 9057.670408]
stack backtrace:
[ 9057.670976] CPU: 7 PID: 30781 Comm: kworker/u16:4 Not tainted 5.14.0-rc2-btrfs-next-93 #1
[ 9057.672030] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org 04/01/2014
[ 9057.673492] Workqueue: btrfs-scrub btrfs_work_helper [btrfs]
[ 9057.674258] Call Trace:
[ 9057.674588] dump_stack_lvl+0x57/0x72
[ 9057.675083] check_noncircular+0xf3/0x110
[ 9057.675611] __lock_acquire+0x130e/0x2210
[ 9057.676132] lock_acquire+0xd7/0x310
[ 9057.676605] ? __btrfs_tree_read_lock+0x24/0x110 [btrfs]
[ 9057.677313] ? lock_is_held_type+0xe8/0x140
[ 9057.677849] down_read_nested+0x4b/0x140
[ 9057.678349] ? __btrfs_tree_read_lock+0x24/0x110 [btrfs]
[ 9057.679068] __btrfs_tree_read_lock+0x24/0x110 [btrfs]
[ 9057.679760] btrfs_read_lock_root_node+0x31/0x40 [btrfs]
[ 9057.680458] btrfs_search_slot+0x537/0xc00 [btrfs]
[ 9057.681083] ? _raw_spin_unlock+0x29/0x40
[ 9057.681594] ? btrfs_find_all_roots_safe+0x11f/0x140 [btrfs]
[ 9057.682336] scrub_print_warning_inode+0x89/0x370 [btrfs]
[ 9057.683058] ? btrfs_find_all_roots_safe+0x11f/0x140 [btrfs]
[ 9057.683834] ? scrub_write_block_to_dev_replace+0xb0/0xb0 [btrfs]
[ 9057.684632] iterate_extent_inodes+0x1e3/0x280 [btrfs]
[ 9057.685316] scrub_print_warning+0x15d/0x2f0 [btrfs]
[ 9057.685977] ? ___ratelimit+0xa4/0x110
[ 9057.686460] scrub_handle_errored_block.isra.0+0x135f/0x1640 [btrfs]
[ 9057.687316] scrub_bio_end_io_worker+0x101/0x2e0 [btrfs]
[ 9057.688021] btrfs_work_helper+0xf8/0x400 [btrfs]
[ 9057.688649] ? lock_is_held_type+0xe8/0x140
[ 9057.689180] process_one_work+0x247/0x5a0
[ 9057.689696] worker_thread+0x55/0x3c0
[ 9057.690175] ? process_one_work+0x5a0/0x5a0
[ 9057.690731] kthread+0x155/0x180
[ 9057.691158] ? set_kthread_struct+0x40/0x40
[ 9057.691697] ret_from_fork+0x22/0x30Fix this by making btrfs_find_all_roots() never attempt to lock the commit_root_sem when it is called from btrfs_qgroup_trace_extent_post().
We can't just pass a non-NULL transaction handle to btrfs_find_all_roots() from btrfs_qgroup_trace_extent_post(), because that would make backref lookup not use commit roots and acquire read locks on extent buffers, and therefore could deadlock when btrfs_qgroup_trace_extent_post() is called from the btrfs_truncate_inode_items() code path which has acquired a write lock on an extent buffer of the subvolume btree.
--- fs/btrfs/backref.c | 6 +++--- fs/btrfs/backref.h | 3 ++- fs/btrfs/delayed-ref.c | 4 ++-- fs/btrfs/qgroup.c | 38 ++++++++++++++++++++++++++++++-------- fs/btrfs/qgroup.h | 2 +- fs/btrfs/tests/qgroup-tests.c | 20 ++++++++++---------- 6 files changed, 48 insertions(+), 25 deletions(-)
fs/btrfs/backref.c +3 -3
@@ -1488,15 +1488,15 @@ static int btrfs_find_all_roots_safe(strint btrfs_find_all_roots (struct btrfs_trans_handle *trans,struct btrfs_fs_info *fs_info,u64 bytenr,u64 time_seq,struct ulist **roots, -bool ignore_offset) +bool ignore_offset,bool skip_commit_root_sem) {int ret; -if (!trans) +if (!trans && !skip_commit_root_sem)down_read (&fs_info->commit_root_sem); ret =btrfs_find_all_roots_safe (trans, fs_info, bytenr, time_seq, roots, ignore_offset); -if (!trans) +if (!trans && !skip_commit_root_sem)up_read (&fs_info->commit_root_sem);return ret; }
fs/btrfs/backref.h +2 -1
@@ -47,7 +47,8 @@ int btrfs_find_all_leafs(struct btrfs_tr const u64 *extent_item_pos, bool ignore_offset);int btrfs_find_all_roots (struct btrfs_trans_handle *trans,struct btrfs_fs_info *fs_info,u64 bytenr, -u64 time_seq,struct ulist **roots,bool ignore_offset); +u64 time_seq,struct ulist **roots,bool ignore_offset, +bool skip_commit_root_sem); char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, u32 name_len, unsigned long name_off, struct extent_buffer *eb_in, u64 parent,
fs/btrfs/delayed-ref.c +2 -2
@@ -1000,7 +1000,7 @@ int btrfs_add_delayed_tree_ref(struct btkmem_cache_free (btrfs_delayed_tree_ref_cachep, ref);if (qrecord_inserted) -btrfs_qgroup_trace_extent_post (fs_info, record); +btrfs_qgroup_trace_extent_post (trans, record);return 0 ; }
@@ -1095,7 +1095,7 @@ int btrfs_add_delayed_data_ref(struct btif (qrecord_inserted) -return btrfs_qgroup_trace_extent_post (fs_info, record); +return btrfs_qgroup_trace_extent_post (trans, record);return 0 ; }
fs/btrfs/qgroup.c +30 -8
@@ -1704,17 +1704,39 @@ int btrfs_qgroup_trace_extent_nolock(strreturn 0 ; } -int btrfs_qgroup_trace_extent_post (struct btrfs_fs_info *fs_info, +int btrfs_qgroup_trace_extent_post (struct btrfs_trans_handle *trans,struct btrfs_qgroup_extent_record *qrecord) {struct ulist *old_root;u64 bytenr = qrecord->bytenr;int ret; - ret =btrfs_find_all_roots (NULL , fs_info, bytenr,0 , &old_root, false); +/* +* We are always called in a context where we are already holding a +* transaction handle. Often we are called when adding a data delayed +* reference from btrfs_truncate_inode_items() (truncating or unlinking), +* in which case we will be holding a write lock on extent buffer from a +* subvolume tree. In this case we can't allow btrfs_find_all_roots() to +* acquire fs_info->commit_root_sem, because that is a higher level lock +* that must be acquired before locking any extent buffers. +* +* So we want btrfs_find_all_roots() to not acquire the commit_root_sem +* but we can't pass it a non-NULL transaction handle, because otherwise +* it would not use commit roots and would lock extent buffers, causing +* a deadlock if it ends up trying to read lock the same extent buffer +* that was previously write locked at btrfs_truncate_inode_items(). +* +* So pass a NULL transaction handle to btrfs_find_all_roots() and +* explicitly tell it to not acquire the commit_root_sem - if we are +* holding a transaction handle we don't need its protection. +*/ +ASSERT (trans !=NULL ); + + ret =btrfs_find_all_roots (NULL , trans->fs_info, bytenr,0 , &old_root, + false, true);if (ret <0 ) { - fs_info->qgroup_flags |=BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT ; -btrfs_warn (fs_info, + trans->fs_info->qgroup_flags |=BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT ; +btrfs_warn (trans->fs_info,"error accounting new delayed refs extent (err code: %d), quota inconsistent" , ret);return 0 ;
@@ -1758,7 +1780,7 @@ int btrfs_qgroup_trace_extent(struct btrkfree (record);return 0 ; } -return btrfs_qgroup_trace_extent_post (fs_info, record); +return btrfs_qgroup_trace_extent_post (trans, record); } int btrfs_qgroup_trace_leaf_items(struct btrfs_trans_handle *trans,
@@ -2629,7 +2651,7 @@ int btrfs_qgroup_account_extents(struct/* Search commit root to find old_roots */ ret =btrfs_find_all_roots (NULL , fs_info, record->bytenr,0 , - &record->old_roots, false); + &record->old_roots, false, false);if (ret <0 ) goto cleanup; }
@@ -2645,7 +2667,7 @@ int btrfs_qgroup_account_extents(struct* current root. It's safe inside commit_transaction(). */ ret =btrfs_find_all_roots (trans, fs_info, - record->bytenr,BTRFS_SEQ_LAST , &new_roots, false); + record->bytenr,BTRFS_SEQ_LAST , &new_roots, false, false);if (ret <0 ) goto cleanup;if (qgroup_to_skip) {
@@ -3179,7 +3201,7 @@ static int qgroup_rescan_leaf(struct btr num_bytes = found.offset; ret =btrfs_find_all_roots (NULL , fs_info, found.objectid,0 , - &roots, false); + &roots, false, false);if (ret <0 ) goto out;/* For rescan, just pass old_roots as NULL */
fs/btrfs/qgroup.h +1 -1
@@ -298,7 +298,7 @@ int btrfs_qgroup_trace_extent_nolock(* using current root, then we can move all expensive backref walk out of * transaction committing, but not now as qgroup accounting will be wrong again. */ -int btrfs_qgroup_trace_extent_post (struct btrfs_fs_info *fs_info, +int btrfs_qgroup_trace_extent_post (struct btrfs_trans_handle *trans,struct btrfs_qgroup_extent_record *qrecord);/*
fs/btrfs/tests/qgroup-tests.c +10 -10
@@ -224,7 +224,7 @@ static int test_no_shared_qgroup(struct* quota. */ ret =btrfs_find_all_roots (&trans, fs_info, nodesize,0 , &old_roots, - false); + false, false);if (ret) {ulist_free (old_roots);test_err ("couldn't find old roots: %d" , ret);
@@ -237,7 +237,7 @@ static int test_no_shared_qgroup(structreturn ret; ret =btrfs_find_all_roots (&trans, fs_info, nodesize,0 , &new_roots, - false); + false, false);if (ret) {ulist_free (old_roots);ulist_free (new_roots);
@@ -261,7 +261,7 @@ static int test_no_shared_qgroup(struct new_roots =NULL ; ret =btrfs_find_all_roots (&trans, fs_info, nodesize,0 , &old_roots, - false); + false, false);if (ret) {ulist_free (old_roots);test_err ("couldn't find old roots: %d" , ret);
@@ -273,7 +273,7 @@ static int test_no_shared_qgroup(structreturn -EINVAL ; ret =btrfs_find_all_roots (&trans, fs_info, nodesize,0 , &new_roots, - false); + false, false);if (ret) {ulist_free (old_roots);ulist_free (new_roots);
@@ -325,7 +325,7 @@ static int test_multiple_refs(struct btr } ret =btrfs_find_all_roots (&trans, fs_info, nodesize,0 , &old_roots, - false); + false, false);if (ret) {ulist_free (old_roots);test_err ("couldn't find old roots: %d" , ret);
@@ -338,7 +338,7 @@ static int test_multiple_refs(struct btrreturn ret; ret =btrfs_find_all_roots (&trans, fs_info, nodesize,0 , &new_roots, - false); + false, false);if (ret) {ulist_free (old_roots);ulist_free (new_roots);
@@ -360,7 +360,7 @@ static int test_multiple_refs(struct btr } ret =btrfs_find_all_roots (&trans, fs_info, nodesize,0 , &old_roots, - false); + false, false);if (ret) {ulist_free (old_roots);test_err ("couldn't find old roots: %d" , ret);
@@ -373,7 +373,7 @@ static int test_multiple_refs(struct btrreturn ret; ret =btrfs_find_all_roots (&trans, fs_info, nodesize,0 , &new_roots, - false); + false, false);if (ret) {ulist_free (old_roots);ulist_free (new_roots);
@@ -401,7 +401,7 @@ static int test_multiple_refs(struct btr } ret =btrfs_find_all_roots (&trans, fs_info, nodesize,0 , &old_roots, - false); + false, false);if (ret) {ulist_free (old_roots);test_err ("couldn't find old roots: %d" , ret);
@@ -414,7 +414,7 @@ static int test_multiple_refs(struct btrreturn ret; ret =btrfs_find_all_roots (&trans, fs_info, nodesize,0 , &new_roots, - false); + false, false);if (ret) {ulist_free (old_roots);ulist_free (new_roots);
Greg Kroah-Hartman
maintainerPATCH 184/223 media: ngene: Fix out-of-bounds bug in ngene_command_config_free_buf()
In reply to Greg Kroah-HartmanFrom: Gustavo A. R. Silva <[email protected]>
commit 8d4abca95ecc82fc8c41912fa0085281f19cc29f upstream.
Fix an 11-year old bug in ngene_command_config_free_buf() while addressing the following warnings caught with -Warray-bounds:
arch/alpha/include/asm/string.h:22:16: warning: '__builtin_memcpy' offset [12, 16] from the object at 'com' is out of the bounds of referenced subobject 'config' with type 'unsigned char' at offset 10 [-Warray-bounds] arch/x86/include/asm/string_32.h:182:25: warning: '__builtin_memcpy' offset [12, 16] from the object at 'com' is out of the bounds of referenced subobject 'config' with type 'unsigned char' at offset 10 [-Warray-bounds]
The problem is that the original code is trying to copy 6 bytes of data into a one-byte size member _config_ of the wrong structue FW_CONFIGURE_BUFFERS, in a single call to memcpy(). This causes a legitimate compiler warning because memcpy() overruns the length of &com.cmd.ConfigureBuffers.config. It seems that the right structure is FW_CONFIGURE_FREE_BUFFERS, instead, because it contains 6 more members apart from the header _hdr_. Also, the name of the function ngene_command_config_free_buf() suggests that the actual intention is to ConfigureFreeBuffers, instead of ConfigureBuffers (which takes place in the function ngene_command_config_buf(), above).
Fix this by enclosing those 6 members of struct FW_CONFIGURE_FREE_BUFFERS into new struct config, and use &com.cmd.ConfigureFreeBuffers.config as the destination address, instead of &com.cmd.ConfigureBuffers.config, when calling memcpy().
This also helps with the ongoing efforts to globally enable -Warray-bounds and get us closer to being able to tighten the FORTIFY_SOURCE routines on memcpy().
--- drivers/media/pci/ngene/ngene-core.c | 2 +- drivers/media/pci/ngene/ngene.h | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-)
drivers/media/pci/ngene/ngene-core.c +1 -1
@@ -385,7 +385,7 @@ static int ngene_command_config_free_buf com.cmd.hdr.Opcode =CMD_CONFIGURE_FREE_BUFFER ; com.cmd.hdr.Length =6 ; -memcpy (&com.cmd.ConfigureBuffers.config, config,6 ); +memcpy (&com.cmd.ConfigureFreeBuffers.config, config,6 ); com.in_len =6 ; com.out_len =0 ;
drivers/media/pci/ngene/ngene.h +8 -6
@@ -407,12 +407,14 @@ enum _BUFFER_CONFIGS {struct FW_CONFIGURE_FREE_BUFFERS {struct FW_HEADER hdr; -u8 UVI1_BufferLength; -u8 UVI2_BufferLength; -u8 TVO_BufferLength; -u8 AUD1_BufferLength; -u8 AUD2_BufferLength; -u8 TVA_BufferLength; +struct { +u8 UVI1_BufferLength; +u8 UVI2_BufferLength; +u8 TVO_BufferLength; +u8 AUD1_BufferLength; +u8 AUD2_BufferLength; +u8 TVA_BufferLength; + } __packed config; } __attribute__ ((__packed__ ));struct FW_CONFIGURE_UART {
Greg Kroah-Hartman
maintainerPATCH 185/223 ixgbe: Fix packet corruption due to missing DMA sync
In reply to Greg Kroah-HartmanFrom: Markus Boehme <[email protected]>
commit 09cfae9f13d51700b0fecf591dcd658fc5375428 upstream.
When receiving a packet with multiple fragments, hardware may still touch the first fragment until the entire packet has been received. The driver therefore keeps the first fragment mapped for DMA until end of packet has been asserted, and delays its dma_sync call until then.
The driver tries to fit multiple receive buffers on one page. When using 3K receive buffers (e.g. using Jumbo frames and legacy-rx is turned off/build_skb is being used) on an architecture with 4K pages, the driver allocates an order 1 compound page and uses one page per receive buffer. To determine the correct offset for a delayed DMA sync of the first fragment of a multi-fragment packet, the driver then cannot just use PAGE_MASK on the DMA address but has to construct a mask based on the actual size of the backing page.
Using PAGE_MASK in the 3K RX buffer/4K page architecture configuration will always sync the first page of a compound page. With the SWIOTLB enabled this can lead to corrupted packets (zeroed out first fragment, re-used garbage from another packet) and various consequences, such as slow/stalling data transfers and connection resets. For example, testing on a link with MTU exceeding 3058 bytes on a host with SWIOTLB enabled (e.g. "iommu=soft swiotlb=262144,force") TCP transfers quickly fizzle out without this patch.
--- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +2 -1
@@ -1825,7 +1825,8 @@ static void ixgbe_dma_sync_frag(struct i struct sk_buff *skb) {if (ring_uses_build_skb (rx_ring)) { -unsigned long offset = (unsigned long )(skb->data) & ~PAGE_MASK ; +unsigned long mask = (unsigned long )ixgbe_rx_pg_size (rx_ring) -1 ; +unsigned long offset = (unsigned long )(skb->data) & mask; dma_sync_single_range_for_cpu(rx_ring->dev, IXGBE_CB(skb)->dma,
Greg Kroah-Hartman
maintainerPATCH 186/223 driver core: auxiliary bus: Fix memory leak when driver_register() fail
In reply to Greg Kroah-HartmanFrom: Peter Ujfalusi <[email protected]>
commit 4afa0c22eed33cfe0c590742387f0d16f32412f3 upstream.
If driver_register() returns with error we need to free the memory allocated for auxdrv->driver.name before returning from __auxiliary_driver_register()
--- drivers/base/auxiliary.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/base/auxiliary.c +7 -1
@@ -231,6 +231,8 @@ EXPORT_SYMBOL_GPL(auxiliary_find_device)int __auxiliary_driver_register (struct auxiliary_driver *auxdrv,struct module *owner,const char *modname) { +int ret; +if (WARN_ON (!auxdrv->probe) ||WARN_ON (!auxdrv->id_table))return -EINVAL ;
@@ -246,7 +248,11 @@ int __auxiliary_driver_register(struct a auxdrv->driver.bus = &auxiliary_bus_type; auxdrv->driver.mod_name = modname; -return driver_register (&auxdrv->driver); + ret =driver_register (&auxdrv->driver); +if (ret) +kfree (auxdrv->driver.name); + +return ret; }EXPORT_SYMBOL_GPL (__auxiliary_driver_register);
Greg Kroah-Hartman
maintainerPATCH 187/223 bus: mhi: pci_generic: Apply no-op for wake using sideband wake boolean
In reply to Greg Kroah-HartmanFrom: Bhaumik Bhatt <[email protected]>
commit 56f6f4c4eb2a710ec8878dd9373d3d2b2eb75f5c upstream.
Devices such as SDX24 do not have the provision for inband wake doorbell in the form of channel 127 and instead have a sideband GPIO for it. Newer devices such as SDX55 or SDX65 support inband wake method by default. Ensure the functionality is used based on this such that device wake stays held when a client driver uses mhi_device_get() API or the equivalent debugfs entry.
--- drivers/bus/mhi/pci_generic.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-)
drivers/bus/mhi/pci_generic.c +19 -8
@@ -32,6 +32,8 @@* @edl: emergency download mode firmware path (if any) * @bar_num: PCI base address register to use for MHI MMIO register space * @dma_data_width: DMA transfer word size (32 or 64 bits) +* @sideband_wake: Devices using dedicated sideband GPIO for wakeup instead +* of inband wake support (such as sdx24) */ struct mhi_pci_dev_info {const struct mhi_controller_config *config;
@@ -40,6 +42,7 @@ struct mhi_pci_dev_info {const char *edl;unsigned int bar_num;unsigned int dma_data_width; +bool sideband_wake; };#define MHI_CHANNEL_CONFIG_UL (ch_num, ch_name, el_count, ev_ring) \
@@ -242,7 +245,8 @@ static const struct mhi_pci_dev_info mhi .edl = "qcom/sdx65m/edl.mbn", .config = &modem_qcom_v1_mhiv_config, .bar_num = MHI_PCI_DEFAULT_BAR_NUM, - .dma_data_width = 32 + .dma_data_width = 32, + .sideband_wake = false, };static const struct mhi_pci_dev_info mhi_qcom_sdx55_info = {
@@ -251,7 +255,8 @@ static const struct mhi_pci_dev_info mhi .edl = "qcom/sdx55m/edl.mbn", .config = &modem_qcom_v1_mhiv_config, .bar_num = MHI_PCI_DEFAULT_BAR_NUM, - .dma_data_width = 32 + .dma_data_width = 32, + .sideband_wake = false, };static const struct mhi_pci_dev_info mhi_qcom_sdx24_info = {
@@ -259,7 +264,8 @@ static const struct mhi_pci_dev_info mhi .edl = "qcom/prog_firehose_sdx24.mbn", .config = &modem_qcom_v1_mhiv_config, .bar_num = MHI_PCI_DEFAULT_BAR_NUM, - .dma_data_width = 32 + .dma_data_width = 32, + .sideband_wake = true, };static const struct mhi_channel_config mhi_quectel_em1xx_channels[] = {
@@ -301,7 +307,8 @@ static const struct mhi_pci_dev_info mhi .edl = "qcom/prog_firehose_sdx24.mbn", .config = &modem_quectel_em1xx_config, .bar_num = MHI_PCI_DEFAULT_BAR_NUM, - .dma_data_width = 32 + .dma_data_width = 32, + .sideband_wake = true, };static const struct mhi_channel_config mhi_foxconn_sdx55_channels[] = {
@@ -339,7 +346,8 @@ static const struct mhi_pci_dev_info mhi .edl = "qcom/sdx55m/edl.mbn", .config = &modem_foxconn_sdx55_config, .bar_num = MHI_PCI_DEFAULT_BAR_NUM, - .dma_data_width = 32 + .dma_data_width = 32, + .sideband_wake = false, };static const struct pci_device_id mhi_pci_id_table[] = {
@@ -640,9 +648,12 @@ static int mhi_pci_probe(struct pci_dev mhi_cntrl->status_cb = mhi_pci_status_cb; mhi_cntrl->runtime_get = mhi_pci_runtime_get; mhi_cntrl->runtime_put = mhi_pci_runtime_put; - mhi_cntrl->wake_get = mhi_pci_wake_get_nop; - mhi_cntrl->wake_put = mhi_pci_wake_put_nop; - mhi_cntrl->wake_toggle = mhi_pci_wake_toggle_nop; + +if (info->sideband_wake) { + mhi_cntrl->wake_get = mhi_pci_wake_get_nop; + mhi_cntrl->wake_put = mhi_pci_wake_put_nop; + mhi_cntrl->wake_toggle = mhi_pci_wake_toggle_nop; + } err =mhi_pci_claim (mhi_cntrl, info->bar_num,DMA_BIT_MASK (info->dma_data_width));if (err)
Greg Kroah-Hartman
maintainerPATCH 188/223 bus: mhi: core: Validate channel ID when processing command completions
In reply to Greg Kroah-HartmanFrom: Bhaumik Bhatt <[email protected]>
commit 546362a9ef2ef40b57c6605f14e88ced507f8dd0 upstream.
MHI reads the channel ID from the event ring element sent by the device which can be any value between 0 and 255. In order to prevent any out of bound accesses, add a check against the maximum number of channels supported by the controller and those channels not configured yet so as to skip processing of that event ring element.
--- drivers/bus/mhi/core/main.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
drivers/bus/mhi/core/main.c +12 -5
@@ -773,11 +773,18 @@ static void mhi_process_cmd_completion(s cmd_pkt =mhi_to_virtual (mhi_ring, ptr); chan =MHI_TRE_GET_CMD_CHID (cmd_pkt); - mhi_chan = &mhi_cntrl->mhi_chan[chan]; -write_lock_bh (&mhi_chan->lock); - mhi_chan->ccs =MHI_TRE_GET_EV_CODE (tre); -complete (&mhi_chan->completion); -write_unlock_bh (&mhi_chan->lock); + +if (chan < mhi_cntrl->max_chan && + mhi_cntrl->mhi_chan[chan].configured) { + mhi_chan = &mhi_cntrl->mhi_chan[chan]; +write_lock_bh (&mhi_chan->lock); + mhi_chan->ccs =MHI_TRE_GET_EV_CODE (tre); +complete (&mhi_chan->completion); +write_unlock_bh (&mhi_chan->lock); + }else { +dev_err (&mhi_cntrl->mhi_dev->dev, +"Completion packet for invalid channel ID: %d\n" , chan); + }mhi_del_ring_element (mhi_cntrl, mhi_ring); }
Greg Kroah-Hartman
maintainerPATCH 189/223 bus: mhi: pci_generic: Fix inbound IPCR channel
In reply to Greg Kroah-HartmanFrom: Loic Poulain <[email protected]>
commit b8a97f2a65388394f433bf0730293a94f7d49046 upstream.
The qrtr-mhi client driver assumes that inbound buffers are automatically allocated and queued by the MHI core, but this doesn't happen for mhi pci devices since IPCR inbound channel is not flagged with auto_queue, causing unusable IPCR (qrtr) feature. Fix that.
--- drivers/bus/mhi/pci_generic.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-)
drivers/bus/mhi/pci_generic.c +17 -1
@@ -75,6 +75,22 @@ struct mhi_pci_dev_info { .doorbell_mode_switch = false, \ } +#define MHI_CHANNEL_CONFIG_DL_AUTOQUEUE (ch_num, ch_name, el_count, ev_ring) \ + { \ + .num = ch_num, \ + .name = ch_name, \ + .num_elements = el_count, \ + .event_ring = ev_ring, \ + .dir = DMA_FROM_DEVICE, \ + .ee_mask = BIT(MHI_EE_AMSS), \ + .pollcfg = 0, \ + .doorbell = MHI_DB_BRST_DISABLE, \ + .lpm_notify = false, \ + .offload_channel = false, \ + .doorbell_mode_switch = false, \ + .auto_queue = true, \ + } +#define MHI_EVENT_CONFIG_CTRL (ev_ring, el_count) \ { \ .num_elements = el_count, \
@@ -213,7 +229,7 @@ static const struct mhi_channel_config mMHI_CHANNEL_CONFIG_UL (14 ,"QMI" ,4 ,0 ),MHI_CHANNEL_CONFIG_DL (15 ,"QMI" ,4 ,0 ),MHI_CHANNEL_CONFIG_UL (20 ,"IPCR" ,8 ,0 ), -MHI_CHANNEL_CONFIG_DL (21 ,"IPCR" ,8 ,0 ), +MHI_CHANNEL_CONFIG_DL_AUTOQUEUE (21 ,"IPCR" ,8 ,0 ),MHI_CHANNEL_CONFIG_UL_FP (34 ,"FIREHOSE" ,32 ,0 ),MHI_CHANNEL_CONFIG_DL_FP (35 ,"FIREHOSE" ,32 ,0 ), MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0", 128, 2),
Greg Kroah-Hartman
maintainerPATCH 190/223 posix-cpu-timers: Fix rearm racing against process tick
In reply to Greg Kroah-HartmanFrom: Frederic Weisbecker <[email protected]>
commit 1a3402d93c73bf6bb4df6d7c2aac35abfc3c50e2 upstream.
Since the process wide cputime counter is started locklessly from posix_cpu_timer_rearm(), it can be concurrently stopped by operations on other timers from the same thread group, such as in the following unlucky scenario:
CPU 0 CPU 1
----- -----
timer_settime(TIMER B)
posix_cpu_timer_rearm(TIMER A)
cpu_clock_sample_group()
(pct->timers_active already true)
handle_posix_cpu_timers()
check_process_timers()
stop_process_timers()
pct->timers_active = false
arm_timer(TIMER A) tick -> run_posix_cpu_timers()
// sees !pct->timers_active, ignore
// our TIMER AFix this with simply locking process wide cputime counting start and timer arm in the same block.
--- kernel/time/posix-cpu-timers.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
kernel/time/posix-cpu-timers.c +5 -5
@@ -991,6 +991,11 @@ static void posix_cpu_timer_rearm(structif (!p) goto out; +/* Protect timer list r/w in arm_timer() */ + sighand =lock_task_sighand (p, &flags); +if (unlikely (sighand ==NULL )) + goto out; +/* * Fetch the current sample and update the timer's expiry time. */
@@ -1001,11 +1006,6 @@ static void posix_cpu_timer_rearm(structbump_cpu_timer (timer, now); -/* Protect timer list r/w in arm_timer() */ - sighand =lock_task_sighand (p, &flags); -if (unlikely (sighand ==NULL )) - goto out; -/* * Now re-arm for the new expiry time. */
Greg Kroah-Hartman
maintainerPATCH 191/223 selftest: use mmap instead of posix_memalign to allocate memory
In reply to Greg Kroah-HartmanFrom: Peter Collingbourne <[email protected]>
commit 0db282ba2c12c1515d490d14a1ff696643ab0f1b upstream.
This test passes pointers obtained from anon_allocate_area to the userfaultfd and mremap APIs. This causes a problem if the system allocator returns tagged pointers because with the tagged address ABI the kernel rejects tagged addresses passed to these APIs, which would end up causing the test to fail. To make this test compatible with such system allocators, stop using the system allocator to allocate memory in anon_allocate_area, and instead just use mmap.
--- tools/testing/selftests/vm/userfaultfd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
tools/testing/selftests/vm/userfaultfd.c +4 -2
@@ -197,8 +197,10 @@ static int anon_release_pages(char *rel_static void anon_allocate_area (void **alloc_area) { -if (posix_memalign (alloc_area, page_size, nr_pages * page_size)) { -fprintf (stderr,"out of memory\n" ); + *alloc_area =mmap (NULL , nr_pages * page_size,PROT_READ |PROT_WRITE , +MAP_ANONYMOUS |MAP_PRIVATE ,-1 ,0 ); +if (*alloc_area ==MAP_FAILED ) +fprintf (stderr,"mmap of anonymous memory failed" ); *alloc_area =NULL ; } }
Re: [PATCH 5.13 191/223] selftest: use mmap instead of posix_memalign to allocate memory
Quoted 40 lines · Greg Kroah-Hartman
From: Peter Collingbourne <[email protected]>
commit
0db282ba2c12c1515d490d14a1ff696643ab0f1bupstream.This test passes pointers obtained from
anon_allocate_areato the userfaultfd and mremap APIs. This causes a problem if the system allocator returns tagged pointers because with the tagged address ABI the kernel rejects tagged addresses passed to these APIs, which would end up causing the test to fail. To make this test compatible with such system allocators, stop using the system allocator to allocate memory inanon_allocate_area, and instead just use mmap.Fixes c47174fc362a ("userfaultfd: selftest")Co-developed-by Lokesh Gidra <[email protected]>Signed-off-by Lokesh Gidra <[email protected]>Signed-off-by Peter Collingbourne <[email protected]>Reviewed-by Catalin Marinas <[email protected]>Cc Vincenzo Frascino <[email protected]>Cc Dave Martin <[email protected]>Cc Will Deacon <[email protected]>Cc Andrea Arcangeli <[email protected]>Cc Alistair Delva <[email protected]>Cc William McVicker <[email protected]>Cc Evgenii Stepanov <[email protected]>Cc Mitch Phillips <[email protected]>Cc Andrey Konovalov <[email protected]>Cc <[email protected]> [5.4]Signed-off-by Andrew Morton <[email protected]>Signed-off-by Linus Torvalds <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- tools/testing/selftests/vm/userfaultfd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
tools/testing/selftests/vm/userfaultfd.c static int anon_release_pages(char *rel_ · line 202
Quoted 8 lines
tools/testing/selftests/vm/userfaultfd.c +3
-2@@ -197,8 +197,10 @@ static int anon_release_pages(char *rel_static void anon_allocate_area (void **alloc_area) { -if (posix_memalign (alloc_area, page_size, nr_pages * page_size)) { -fprintf (stderr,"out of memory\n" ); + *alloc_area =mmap (NULL , nr_pages * page_size,PROT_READ |PROT_WRITE , +MAP_ANONYMOUS |MAP_PRIVATE ,-1 ,0 ); +if (*alloc_area ==MAP_FAILED )
Hi Greg,
It looks like your backport of this patch (and the backports to stable kernels) are missing a left brace here.
Peter
Quoted 6 lines
tools/testing/selftests/vm/userfaultfd.c +1
-0+fprintf (stderr,"mmap of anonymous memory failed" ); *alloc_area =NULL ; } }
Greg Kroah-Hartman
maintainerRe: [PATCH 5.13 191/223] selftest: use mmap instead of posix_memalign to allocate memory
Quoted 53 lines · Peter Collingbourne
Quoted 40 lines · Greg Kroah-Hartman
From: Peter Collingbourne <[email protected]>
commit
0db282ba2c12c1515d490d14a1ff696643ab0f1bupstream.This test passes pointers obtained from
anon_allocate_areato the userfaultfd and mremap APIs. This causes a problem if the system allocator returns tagged pointers because with the tagged address ABI the kernel rejects tagged addresses passed to these APIs, which would end up causing the test to fail. To make this test compatible with such system allocators, stop using the system allocator to allocate memory inanon_allocate_area, and instead just use mmap.Fixes c47174fc362a ("userfaultfd: selftest")Co-developed-by Lokesh Gidra <[email protected]>Signed-off-by Lokesh Gidra <[email protected]>Signed-off-by Peter Collingbourne <[email protected]>Reviewed-by Catalin Marinas <[email protected]>Cc Vincenzo Frascino <[email protected]>Cc Dave Martin <[email protected]>Cc Will Deacon <[email protected]>Cc Andrea Arcangeli <[email protected]>Cc Alistair Delva <[email protected]>Cc William McVicker <[email protected]>Cc Evgenii Stepanov <[email protected]>Cc Mitch Phillips <[email protected]>Cc Andrey Konovalov <[email protected]>Cc <[email protected]> [5.4]Signed-off-by Andrew Morton <[email protected]>Signed-off-by Linus Torvalds <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- tools/testing/selftests/vm/userfaultfd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)tools/testing/selftests/vm/userfaultfd.c static int anon_release_pages(char *rel_ · line 202
Quoted 8 lines
tools/testing/selftests/vm/userfaultfd.c +3
-2@@ -197,8 +197,10 @@ static int anon_release_pages(char *rel_static void anon_allocate_area (void **alloc_area) { -if (posix_memalign (alloc_area, page_size, nr_pages * page_size)) { -fprintf (stderr,"out of memory\n" ); + *alloc_area =mmap (NULL , nr_pages * page_size,PROT_READ |PROT_WRITE , +MAP_ANONYMOUS |MAP_PRIVATE ,-1 ,0 ); +if (*alloc_area ==MAP_FAILED )Hi Greg,
Quoted 2 lines
It looks like your backport of this patch (and the backports to stable kernels) are missing a left brace here.
Already fixed up in the latest -rc releases, right?
thanks,
greg k-h
Re: [PATCH 5.13 191/223] selftest: use mmap instead of posix_memalign to allocate memory
Quoted 55 lines · Greg Kroah-Hartman
Quoted 53 lines · Peter Collingbourne
Quoted 40 lines · Greg Kroah-Hartman
From: Peter Collingbourne <[email protected]>
commit
0db282ba2c12c1515d490d14a1ff696643ab0f1bupstream.This test passes pointers obtained from
anon_allocate_areato the userfaultfd and mremap APIs. This causes a problem if the system allocator returns tagged pointers because with the tagged address ABI the kernel rejects tagged addresses passed to these APIs, which would end up causing the test to fail. To make this test compatible with such system allocators, stop using the system allocator to allocate memory inanon_allocate_area, and instead just use mmap.Fixes c47174fc362a ("userfaultfd: selftest")Co-developed-by Lokesh Gidra <[email protected]>Signed-off-by Lokesh Gidra <[email protected]>Signed-off-by Peter Collingbourne <[email protected]>Reviewed-by Catalin Marinas <[email protected]>Cc Vincenzo Frascino <[email protected]>Cc Dave Martin <[email protected]>Cc Will Deacon <[email protected]>Cc Andrea Arcangeli <[email protected]>Cc Alistair Delva <[email protected]>Cc William McVicker <[email protected]>Cc Evgenii Stepanov <[email protected]>Cc Mitch Phillips <[email protected]>Cc Andrey Konovalov <[email protected]>Cc <[email protected]> [5.4]Signed-off-by Andrew Morton <[email protected]>Signed-off-by Linus Torvalds <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- tools/testing/selftests/vm/userfaultfd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)tools/testing/selftests/vm/userfaultfd.c static int anon_release_pages(char *rel_ · line 202
Quoted 8 lines
tools/testing/selftests/vm/userfaultfd.c +3
-2@@ -197,8 +197,10 @@ static int anon_release_pages(char *rel_static void anon_allocate_area (void **alloc_area) { -if (posix_memalign (alloc_area, page_size, nr_pages * page_size)) { -fprintf (stderr,"out of memory\n" ); + *alloc_area =mmap (NULL , nr_pages * page_size,PROT_READ |PROT_WRITE , +MAP_ANONYMOUS |MAP_PRIVATE ,-1 ,0 ); +if (*alloc_area ==MAP_FAILED )Hi Greg,
Quoted 4 lines
Quoted 2 lines
It looks like your backport of this patch (and the backports to stable kernels) are missing a left brace here.
Already fixed up in the latest -rc releases, right?
It looks like you fixed it on linux-4.19.y and linux-5.4.y, but not linux-4.14.y, linux-5.10.y or linux-5.13.y.
Peter
Greg Kroah-Hartman
maintainerRe: [PATCH 5.13 191/223] selftest: use mmap instead of posix_memalign to allocate memory
Quoted 57 lines · Peter Collingbourne
Quoted 55 lines · Greg Kroah-Hartman
Quoted 53 lines · Peter Collingbourne
Quoted 40 lines · Greg Kroah-Hartman
From: Peter Collingbourne <[email protected]>
commit
0db282ba2c12c1515d490d14a1ff696643ab0f1bupstream.This test passes pointers obtained from
anon_allocate_areato the userfaultfd and mremap APIs. This causes a problem if the system allocator returns tagged pointers because with the tagged address ABI the kernel rejects tagged addresses passed to these APIs, which would end up causing the test to fail. To make this test compatible with such system allocators, stop using the system allocator to allocate memory inanon_allocate_area, and instead just use mmap.Fixes c47174fc362a ("userfaultfd: selftest")Co-developed-by Lokesh Gidra <[email protected]>Signed-off-by Lokesh Gidra <[email protected]>Signed-off-by Peter Collingbourne <[email protected]>Reviewed-by Catalin Marinas <[email protected]>Cc Vincenzo Frascino <[email protected]>Cc Dave Martin <[email protected]>Cc Will Deacon <[email protected]>Cc Andrea Arcangeli <[email protected]>Cc Alistair Delva <[email protected]>Cc William McVicker <[email protected]>Cc Evgenii Stepanov <[email protected]>Cc Mitch Phillips <[email protected]>Cc Andrey Konovalov <[email protected]>Cc <[email protected]> [5.4]Signed-off-by Andrew Morton <[email protected]>Signed-off-by Linus Torvalds <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- tools/testing/selftests/vm/userfaultfd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)tools/testing/selftests/vm/userfaultfd.c static int anon_release_pages(char *rel_ · line 202
Quoted 8 lines
tools/testing/selftests/vm/userfaultfd.c +3
-2@@ -197,8 +197,10 @@ static int anon_release_pages(char *rel_static void anon_allocate_area (void **alloc_area) { -if (posix_memalign (alloc_area, page_size, nr_pages * page_size)) { -fprintf (stderr,"out of memory\n" ); + *alloc_area =mmap (NULL , nr_pages * page_size,PROT_READ |PROT_WRITE , +MAP_ANONYMOUS |MAP_PRIVATE ,-1 ,0 ); +if (*alloc_area ==MAP_FAILED )Hi Greg,
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
It looks like your backport of this patch (and the backports to stable kernels) are missing a left brace here.
Already fixed up in the latest -rc releases, right?
It looks like you fixed it on linux-4.19.y and linux-5.4.y, but not linux-4.14.y, linux-5.10.y or linux-5.13.y.
4.14 had not had a release with this in it yet (it is in the queue), I missed that I also broke this on 5.10 and 5.13 so will go add it there as well.
thanks!
greg k-h
Greg Kroah-Hartman
maintainerPATCH 192/223 io_uring: explicitly count entries for poll reqs
In reply to Greg Kroah-HartmanFrom: Pavel Begunkov <[email protected]>
commit 68b11e8b1562986c134764433af64e97d30c9fc0 upstream.
If __io_queue_proc() fails to add a second poll entry, e.g. kmalloc() failed, but it goes on with a third waitqueue, it may succeed and overwrite the error status. Count the number of poll entries we added, so we can set pt->error to zero at the beginning and find out when the mentioned scenario happens.
--- fs/io_uring.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
fs/io_uring.c +10 -6
@@ -4805,6 +4805,7 @@ IO_NETOP_FN(recv);struct io_poll_table {struct poll_table_struct pt;struct io_kiocb *req; +int nr_entries;int error; };
@@ -5002,11 +5003,11 @@ static void __io_queue_proc(struct io_postruct io_kiocb *req = pt->req;/* -* If poll->head is already set, it's because the file being polled -* uses multiple waitqueues for poll handling (eg one for read, one -* for write). Setup a separate io_poll_iocb if this happens. +* The file being polled uses multiple waitqueues for poll handling +* (e.g. one for read, one for write). Setup a separate io_poll_iocb +* if this happens. */ -if (unlikely (poll->head)) { +if (unlikely (pt->nr_entries)) {struct io_poll_iocb *poll_one = poll;/* already have a 2nd entry, fail a third attempt */
@@ -5034,7 +5035,7 @@ static void __io_queue_proc(struct io_po *poll_ptr = poll; } - pt->error =0 ; + pt->nr_entries++; poll->head = head;if (poll->events &EPOLLEXCLUSIVE )
@@ -5112,9 +5113,12 @@ static __poll_t __io_arm_poll_handler(st ipt->pt._key = mask; ipt->req = req; - ipt->error = -EINVAL ; + ipt->error =0 ; + ipt->nr_entries =0 ; mask =vfs_poll (req->file, &ipt->pt) & poll->events; +if (unlikely (!ipt->nr_entries) && !ipt->error) + ipt->error = -EINVAL ;spin_lock_irq (&ctx->completion_lock);if (likely (poll->head)) {
Greg Kroah-Hartman
maintainerPATCH 193/223 io_uring: remove double poll entry on arm failure
In reply to Greg Kroah-HartmanFrom: Pavel Begunkov <[email protected]>
commit 46fee9ab02cb24979bbe07631fc3ae95ae08aa3e upstream.
__io_queue_proc() can enqueue both poll entries and still fail afterwards, so the callers trying to cancel it should also try to remove the second poll entry (if any).
For example, it may leave the request alive referencing a io_uring context but not accessible for cancellation:
[ 282.599913][ T1620] task:iou-sqp-23145 state:D stack:28720 pid:23155 ppid: 8844 flags:0x00004004 [ 282.609927][ T1620] Call Trace: [ 282.613711][ T1620] __schedule+0x93a/0x26f0 [ 282.634647][ T1620] schedule+0xd3/0x270 [ 282.638874][ T1620] io_uring_cancel_generic+0x54d/0x890 [ 282.660346][ T1620] io_sq_thread+0xaac/0x1250 [ 282.696394][ T1620] ret_from_fork+0x1f/0x30
--- fs/io_uring.c | 2 ++ 1 file changed, 2 insertions(+)
fs/io_uring.c +2 -0
@@ -5121,6 +5121,8 @@ static __poll_t __io_arm_poll_handler(st ipt->error = -EINVAL ;spin_lock_irq (&ctx->completion_lock); +if (ipt->error) +io_poll_remove_double (req);if (likely (poll->head)) {spin_lock (&poll->head->lock);if (unlikely (list_empty (&poll->wait.entry))) {
Greg Kroah-Hartman
maintainerPATCH 194/223 io_uring: fix early fdput() of file
In reply to Greg Kroah-HartmanFrom: Jens Axboe <[email protected]>
commit 0cc936f74bcacb039b7533aeac0a887dfc896bf6 upstream.
A previous commit shuffled some code around, and inadvertently used struct file after fdput() had been called on it. As we can't touch the file post fdput() dropping our reference, move the fdput() to after that has been done.
--- fs/io_uring.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
fs/io_uring.c +4 -2
@@ -7953,9 +7953,11 @@ static int io_sq_offload_create(struct i f =fdget (p->wq_fd);if (!f.file)return -ENXIO ; -fdput (f); -if (f.file->f_op != &io_uring_fops) +if (f.file->f_op != &io_uring_fops) { +fdput (f);return -EINVAL ; + } +fdput (f); }if (ctx->flags &IORING_SETUP_SQPOLL ) {struct task_struct *tsk;
Greg Kroah-Hartman
maintainerPATCH 195/223 userfaultfd: do not untag user pointers
In reply to Greg Kroah-HartmanFrom: Peter Collingbourne <[email protected]>
commit e71e2ace5721a8b921dca18b045069e7bb411277 upstream.
Patch series "userfaultfd: do not untag user pointers", v5.
If a user program uses userfaultfd on ranges of heap memory, it may end up passing a tagged pointer to the kernel in the range.start field of the UFFDIO_REGISTER ioctl. This can happen when using an MTE-capable allocator, or on Android if using the Tagged Pointers feature for MTE readiness [1].
When a fault subsequently occurs, the tag is stripped from the fault address returned to the application in the fault.address field of struct uffd_msg. However, from the application's perspective, the tagged address *is* the memory address, so if the application is unaware of memory tags, it may get confused by receiving an address that is, from its point of view, outside of the bounds of the allocation. We observed this behavior in the kselftest for userfaultfd [2] but other applications could have the same problem.
Address this by not untagging pointers passed to the userfaultfd ioctls. Instead, let the system call fail. Also change the kselftest to use mmap so that it doesn't encounter this problem.
[1] https://source.android.com/devices/tech/debug/tagged-pointers
[2] tools/testing/selftests/vm/userfaultfd.c
This patch (of 2):
Do not untag pointers passed to the userfaultfd ioctls. Instead, let the system call fail. This will provide an early indication of problems with tag-unaware userspace code instead of letting the code get confused later, and is consistent with how we decided to handle brk/mmap/mremap in commit dcde237319e6 ("mm: Avoid creating virtual address aliases in brk()/mmap()/mremap()"), as well as being consistent with the existing tagged address ABI documentation relating to how ioctl arguments are handled.
The code change is a revert of commit 7d0325749a6c ("userfaultfd: untag user pointers") plus some fixups to some additional calls to validate_range that have appeared since then.
[1] https://source.android.com/devices/tech/debug/tagged-pointers
[2] tools/testing/selftests/vm/userfaultfd.c
--- Documentation/arm64/tagged-address-abi.rst | 26 ++++++++++++++++++-------- fs/userfaultfd.c | 26 ++++++++++++-------------- 2 files changed, 30 insertions(+), 22 deletions(-)
Documentation/arm64/tagged-address-abi.rst +18 -8
@@ -45,14 +45,24 @@ how the user addresses are used by the k 1. User addresses not accessed by the kernel but used for address space management (e.g. ``mprotect()``, ``madvise()``). The use of valid - tagged pointers in this context is allowed with the exception of - ``brk()``, ``mmap()`` and the ``new_address`` argument to - ``mremap()`` as these have the potential to alias with existing - user addresses. - - NOTE: This behaviour changed in v5.6 and so some earlier kernels may - incorrectly accept valid tagged pointers for the ``brk()``, - ``mmap()`` and ``mremap()`` system calls. + tagged pointers in this context is allowed with these exceptions: + + - ``brk()``, ``mmap()`` and the ``new_address`` argument to + ``mremap()`` as these have the potential to alias with existing + user addresses. + + NOTE: This behaviour changed in v5.6 and so some earlier kernels may + incorrectly accept valid tagged pointers for the ``brk()``, + ``mmap()`` and ``mremap()`` system calls. + + - The ``range.start``, ``start`` and ``dst`` arguments to the + ``UFFDIO_*`` ``ioctl()``s used on a file descriptor obtained from + ``userfaultfd()``, as fault addresses subsequently obtained by reading + the file descriptor will be untagged, which may otherwise confuse + tag-unaware programs. + + NOTE: This behaviour changed in v5.14 and so some earlier kernels may + incorrectly accept valid tagged pointers for this system call. 2. User addresses accessed by the kernel (e.g. ``write()``). This ABI relaxation is disabled by default and the application thread needs to
fs/userfaultfd.c +12 -14
@@ -1236,23 +1236,21 @@ static __always_inline void wake_userfau } static __always_inline int validate_range(struct mm_struct *mm, -__u64 *start,__u64 len) +__u64 start,__u64 len) {__u64 task_size = mm->task_size; - *start =untagged_addr (*start); - -if (*start & ~PAGE_MASK ) +if (start & ~PAGE_MASK )return -EINVAL ;if (len & ~PAGE_MASK )return -EINVAL ;if (!len)return -EINVAL ; -if (*start < mmap_min_addr) +if (start < mmap_min_addr)return -EINVAL ; -if (*start >= task_size) +if (start >= task_size)return -EINVAL ; -if (len > task_size - *start) +if (len > task_size - start)return -EINVAL ;return 0 ; }
@@ -1313,7 +1311,7 @@ static int userfaultfd_register(struct u vm_flags |=VM_UFFD_MINOR ; } - ret =validate_range (mm, &uffdio_register.range.start, + ret =validate_range (mm, uffdio_register.range.start, uffdio_register.range.len);if (ret) goto out;
@@ -1519,7 +1517,7 @@ static int userfaultfd_unregister(structif (copy_from_user (&uffdio_unregister, buf,sizeof (uffdio_unregister))) goto out; - ret =validate_range (mm, &uffdio_unregister.start, + ret =validate_range (mm, uffdio_unregister.start, uffdio_unregister.len);if (ret) goto out;
@@ -1668,7 +1666,7 @@ static int userfaultfd_wake(struct userfif (copy_from_user (&uffdio_wake, buf,sizeof (uffdio_wake))) goto out; - ret =validate_range (ctx->mm, &uffdio_wake.start, uffdio_wake.len); + ret =validate_range (ctx->mm, uffdio_wake.start, uffdio_wake.len);if (ret) goto out;
@@ -1708,7 +1706,7 @@ static int userfaultfd_copy(struct userf sizeof(uffdio_copy)-sizeof(__s64))) goto out; - ret =validate_range (ctx->mm, &uffdio_copy.dst, uffdio_copy.len); + ret =validate_range (ctx->mm, uffdio_copy.dst, uffdio_copy.len);if (ret) goto out;/*
@@ -1765,7 +1763,7 @@ static int userfaultfd_zeropage(struct u sizeof(uffdio_zeropage)-sizeof(__s64))) goto out; - ret =validate_range (ctx->mm, &uffdio_zeropage.range.start, + ret =validate_range (ctx->mm, uffdio_zeropage.range.start, uffdio_zeropage.range.len);if (ret) goto out;
@@ -1815,7 +1813,7 @@ static int userfaultfd_writeprotect(stru sizeof(struct uffdio_writeprotect)))return -EFAULT ; - ret =validate_range (ctx->mm, &uffdio_wp.range.start, + ret =validate_range (ctx->mm, uffdio_wp.range.start, uffdio_wp.range.len);if (ret)return ret;
@@ -1863,7 +1861,7 @@ static int userfaultfd_continue(struct u sizeof(uffdio_continue) - (sizeof(__s64)))) goto out; - ret =validate_range (ctx->mm, &uffdio_continue.range.start, + ret =validate_range (ctx->mm, uffdio_continue.range.start, uffdio_continue.range.len);if (ret) goto out;
Greg Kroah-Hartman
maintainerPATCH 196/223 kfence: move the size check to the beginning of __kfence_alloc()
In reply to Greg Kroah-HartmanFrom: Alexander Potapenko <[email protected]>
commit 235a85cb32bb123854ad31de46fdbf04c1d57cda upstream.
Check the allocation size before toggling kfence_allocation_gate.
This way allocations that can't be served by KFENCE will not result in waiting for another CONFIG_KFENCE_SAMPLE_INTERVAL without allocating anything.
--- mm/kfence/core.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
mm/kfence/core.c +7 -3
@@ -734,6 +734,13 @@ void kfence_shutdown_cache(struct kmem_cvoid *__kfence_alloc (struct kmem_cache *s,size_t size,gfp_t flags) {/* +* Perform size check before switching kfence_allocation_gate, so that +* we don't disable KFENCE without making an allocation. +*/ +if (size >PAGE_SIZE ) +return NULL ; + +/* * allocation_gate only needs to become non-zero, so it doesn't make * sense to continue writing to it and pay the associated contention * cost, in case we have a large number of concurrent allocations.
@@ -757,9 +764,6 @@ void *__kfence_alloc(struct kmem_cache *if (!READ_ONCE (kfence_enabled))return NULL ; -if (size >PAGE_SIZE ) -return NULL ; -return kfence_guarded_alloc (s, size, flags); }
Greg Kroah-Hartman
maintainerPATCH 197/223 kfence: skip all GFP_ZONEMASK allocations
In reply to Greg Kroah-HartmanFrom: Alexander Potapenko <[email protected]>
commit 236e9f1538523d3d380dda1cc99571d587058f37 upstream.
Allocation requests outside ZONE_NORMAL (MOVABLE, HIGHMEM or DMA) cannot be fulfilled by KFENCE, because KFENCE memory pool is located in a zone different from the requested one.
Because callers of kmem_cache_alloc() may actually rely on the allocation to reside in the requested zone (e.g. memory allocations done with __GFP_DMA must be DMAable), skip all allocations done with GFP_ZONEMASK and/or respective SLAB flags (SLAB_CACHE_DMA and SLAB_CACHE_DMA32).
--- mm/kfence/core.c | 9 +++++++++ 1 file changed, 9 insertions(+)
mm/kfence/core.c +9 -0
@@ -741,6 +741,15 @@ void *__kfence_alloc(struct kmem_cache *return NULL ;/* +* Skip allocations from non-default zones, including DMA. We cannot +* guarantee that pages in the KFENCE pool will have the requested +* properties (e.g. reside in DMAable memory). +*/ +if ((flags &GFP_ZONEMASK ) || + (s->flags & (SLAB_CACHE_DMA |SLAB_CACHE_DMA32 ))) +return NULL ; + +/* * allocation_gate only needs to become non-zero, so it doesn't make * sense to continue writing to it and pay the associated contention * cost, in case we have a large number of concurrent allocations.
Greg Kroah-Hartman
maintainerPATCH 198/223 mm: call flush_dcache_page() in memcpy_to_page() and memzero_page()
In reply to Greg Kroah-HartmanFrom: Christoph Hellwig <[email protected]>
commit 8dad53a11f8d94dceb540a5f8f153484f42be84b upstream.
memcpy_to_page and memzero_page can write to arbitrary pages, which could be in the page cache or in high memory, so call flush_kernel_dcache_pages to flush the dcache.
This is a problem when using these helpers on dcache challeneged architectures. Right now there are just a few users, chances are no one used the PC floppy driver, the aha1542 driver for an ISA SCSI HBA, and a few advanced and optional btrfs and ext4 features on those platforms yet since the conversion.
--- include/linux/highmem.h | 2 ++ 1 file changed, 2 insertions(+)
include/linux/highmem.h +2 -0
@@ -329,6 +329,7 @@ static inline void memcpy_to_page(structVM_BUG_ON (offset + len >PAGE_SIZE );memcpy (to + offset, from, len); +flush_dcache_page (page);kunmap_local (to); }
@@ -336,6 +337,7 @@ static inline void memzero_page(struct p {char *addr =kmap_atomic (page);memset (addr + offset,0 , len); +flush_dcache_page (page);kunmap_atomic (addr); }
Greg Kroah-Hartman
maintainerPATCH 199/223 mm: page_alloc: fix page_poison=1 / INIT_ON_ALLOC_DEFAULT_ON interaction
In reply to Greg Kroah-HartmanFrom: Sergei Trofimovich <[email protected]>
commit 69e5d322a2fb86173fde8bad26e8eb38cad1b1e9 upstream.
To reproduce the failure we need the following system:
- kernel command: page_poison=1 init_on_free=0 init_on_alloc=0
- kernel config:
* CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y
* CONFIG_INIT_ON_FREE_DEFAULT_ON=y
* CONFIG_PAGE_POISONING=y
Resulting in:
0000000085629bdd: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0000000022861832: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000000c597f5b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
CPU: 11 PID: 15195 Comm: bash Kdump: loaded Tainted: G U O 5.13.1-gentoo-x86_64 #1
Hardware name: System manufacturer System Product Name/PRIME Z370-A, BIOS 2801 01/13/2021
Call Trace:
dump_stack+0x64/0x7c
__kernel_unpoison_pages.cold+0x48/0x84
post_alloc_hook+0x60/0xa0
get_page_from_freelist+0xdb8/0x1000
__alloc_pages+0x163/0x2b0
__get_free_pages+0xc/0x30
pgd_alloc+0x2e/0x1a0
mm_init+0x185/0x270
dup_mm+0x6b/0x4f0
copy_process+0x190d/0x1b10
kernel_clone+0xba/0x3b0
__do_sys_clone+0x8f/0xb0
do_syscall_64+0x68/0x80
entry_SYSCALL_64_after_hwframe+0x44/0xaeBefore commit 51cba1ebc60d ("init_on_alloc: Optimize static branches") init_on_alloc never enabled static branch by default. It could only be enabed explicitly by init_mem_debugging_and_hardening().
But after commit 51cba1ebc60d, a static branch could already be enabled by default. There was no code to ever disable it. That caused page_poison=1 / init_on_free=1 conflict.
This change extends init_mem_debugging_and_hardening() to also disable static branch disabling.
--- mm/page_alloc.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-)
mm/page_alloc.c +16 -13
@@ -801,21 +801,24 @@ void init_mem_debugging_and_hardening(vo }#endif -if (_init_on_alloc_enabled_early) { -if (page_poisoning_requested) -pr_info ("mem auto-init: CONFIG_PAGE_POISONING is on, " -"will take precedence over init_on_alloc\n" ); -else -static_branch_enable (&init_on_alloc); - } -if (_init_on_free_enabled_early) { -if (page_poisoning_requested) -pr_info ("mem auto-init: CONFIG_PAGE_POISONING is on, " -"will take precedence over init_on_free\n" ); -else -static_branch_enable (&init_on_free); +if ((_init_on_alloc_enabled_early || _init_on_free_enabled_early) && + page_poisoning_requested) { +pr_info ("mem auto-init: CONFIG_PAGE_POISONING is on, " +"will take precedence over init_on_alloc and init_on_free\n" ); + _init_on_alloc_enabled_early = false; + _init_on_free_enabled_early = false; } +if (_init_on_alloc_enabled_early) +static_branch_enable (&init_on_alloc); +else +static_branch_disable (&init_on_alloc); + +if (_init_on_free_enabled_early) +static_branch_enable (&init_on_free); +else +static_branch_disable (&init_on_free); +#ifdef CONFIG_DEBUG_PAGEALLOC if (!debug_pagealloc_enabled ())return ;
Greg Kroah-Hartman
maintainerPATCH 200/223 memblock: make for_each_mem_range() traverse MEMBLOCK_HOTPLUG regions
In reply to Greg Kroah-HartmanFrom: Mike Rapoport <[email protected]>
commit 79e482e9c3ae86e849c701c846592e72baddda5a upstream.
Commit b10d6bca8720 ("arch, drivers: replace for_each_membock() with for_each_mem_range()") didn't take into account that when there is movable_node parameter in the kernel command line, for_each_mem_range() would skip ranges marked with MEMBLOCK_HOTPLUG.
The page table setup code in POWER uses for_each_mem_range() to create the linear mapping of the physical memory and since the regions marked as MEMORY_HOTPLUG are skipped, they never make it to the linear map.
A later access to the memory in those ranges will fail:
BUG: Unable to handle kernel data access on write at 0xc000000400000000
Faulting instruction address: 0xc00000000008a3c0
Oops: Kernel access of bad area, sig: 11 [#1]
LE PAGE_SIZE=64K MMU=Radix SMP NR_CPUS=2048 NUMA pSeries
Modules linked in:
CPU: 0 PID: 53 Comm: kworker/u2:0 Not tainted 5.13.0 #7
NIP: c00000000008a3c0 LR: c0000000003c1ed8 CTR: 0000000000000040
REGS: c000000008a57770 TRAP: 0300 Not tainted (5.13.0)
MSR: 8000000002009033 <SF,VEC,EE,ME,IR,DR,RI,LE> CR: 84222202 XER: 20040000
CFAR: c0000000003c1ed4 DAR: c000000400000000 DSISR: 42000000 IRQMASK: 0
GPR00: c0000000003c1ed8 c000000008a57a10 c0000000019da700 c000000400000000
GPR04: 0000000000000280 0000000000000180 0000000000000400 0000000000000200
GPR08: 0000000000000100 0000000000000080 0000000000000040 0000000000000300
GPR12: 0000000000000380 c000000001bc0000 c0000000001660c8 c000000006337e00
GPR16: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
GPR20: 0000000040000000 0000000020000000 c000000001a81990 c000000008c30000
GPR24: c000000008c20000 c000000001a81998 000fffffffff0000 c000000001a819a0
GPR28: c000000001a81908 c00c000001000000 c000000008c40000 c000000008a64680
NIP clear_user_page+0x50/0x80
LR __handle_mm_fault+0xc88/0x1910
Call Trace:
__handle_mm_fault+0xc44/0x1910 (unreliable)
handle_mm_fault+0x130/0x2a0
__get_user_pages+0x248/0x610
__get_user_pages_remote+0x12c/0x3e0
get_arg_page+0x54/0xf0
copy_string_kernel+0x11c/0x210
kernel_execve+0x16c/0x220
call_usermodehelper_exec_async+0x1b0/0x2f0
ret_from_kernel_thread+0x5c/0x70
Instruction dump:
79280fa4 79271764 79261f24 794ae8e2 7ca94214 7d683a14 7c893a14 7d893050
7d4903a6 60000000 60000000 60000000 <7c001fec> 7c091fec 7c081fec 7c051fec
---[ end trace 490b8c67e6075e09 ]---Making for_each_mem_range() include MEMBLOCK_HOTPLUG regions in the traversal fixes this issue.
--- include/linux/memblock.h | 4 ++-- mm/memblock.c | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-)
include/linux/memblock.h +2 -2
@@ -207,7 +207,7 @@ static inline void __next_physmem_range(*/ #define for_each_mem_range (i, p_start, p_end) \ __for_each_mem_range(i, &memblock.memory, NULL, NUMA_NO_NODE, \ - MEMBLOCK_NONE, p_start, p_end, NULL) + MEMBLOCK_HOTPLUG, p_start, p_end, NULL)/** * for_each_mem_range_rev - reverse iterate through memblock areas from
@@ -218,7 +218,7 @@ static inline void __next_physmem_range(*/ #define for_each_mem_range_rev (i, p_start, p_end) \ __for_each_mem_range_rev(i, &memblock.memory, NULL, NUMA_NO_NODE, \ - MEMBLOCK_NONE, p_start, p_end, NULL) + MEMBLOCK_HOTPLUG, p_start, p_end, NULL)/** * for_each_reserved_mem_range - iterate over all reserved memblock areas
mm/memblock.c +2 -1
@@ -940,7 +940,8 @@ static bool should_skip_region(struct mereturn true;/* skip hotpluggable memory regions if needed */ -if (movable_node_is_enabled () &&memblock_is_hotpluggable (m)) +if (movable_node_is_enabled () &&memblock_is_hotpluggable (m) && + !(flags &MEMBLOCK_HOTPLUG ))return true;/* if we want mirror memory skip non-mirror memory regions */
Greg Kroah-Hartman
maintainerPATCH 201/223 mm: fix the deadlock in finish_fault()
In reply to Greg Kroah-HartmanFrom: Qi Zheng <[email protected]>
commit e4dc3489143f84f7ed30be58b886bb6772f229b9 upstream.
Commit 63f3655f9501 ("mm, memcg: fix reclaim deadlock with writeback") fix the following ABBA deadlock by pre-allocating the pte page table without holding the page lock.
lock_page(A) SetPageWriteback(A) unlock_page(A)
lock_page(B)
lock_page(B)
pte_alloc_one
shrink_page_list
wait_on_page_writeback(A)
SetPageWriteback(B) unlock_page(B)
# flush A, B to clear the writeback
Commit f9ce0be71d1f ("mm: Cleanup faultaround and finish_fault() codepaths") reworked the relevant code but ignored this race. This will cause the deadlock above to appear again, so fix it.
--- mm/memory.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
mm/memory.c +10 -1
@@ -3891,8 +3891,17 @@ vm_fault_t finish_fault(struct vm_faultreturn ret; } -if (unlikely (pte_alloc (vma->vm_mm, vmf->pmd))) +if (vmf->prealloc_pte) { + vmf->ptl =pmd_lock (vma->vm_mm, vmf->pmd); +if (likely (pmd_none (*vmf->pmd))) { +mm_inc_nr_ptes (vma->vm_mm); +pmd_populate (vma->vm_mm, vmf->pmd, vmf->prealloc_pte); + vmf->prealloc_pte =NULL ; + } +spin_unlock (vmf->ptl); + }else if (unlikely (pte_alloc (vma->vm_mm, vmf->pmd))) {return VM_FAULT_OOM ; + } }/* See comment in handle_pte_fault() */
Greg Kroah-Hartman
maintainerPATCH 202/223 hugetlbfs: fix mount mode command line processing
In reply to Greg Kroah-HartmanFrom: Mike Kravetz <[email protected]>
commit e0f7e2b2f7e7864238a4eea05cc77ae1be2bf784 upstream.
In commit 32021982a324 ("hugetlbfs: Convert to fs_context") processing of the mount mode string was changed from match_octal() to fsparam_u32.
This changed existing behavior as match_octal does not require octal values to have a '0' prefix, but fsparam_u32 does.
Use fsparam_u32oct which provides the same behavior as match_octal.
--- fs/hugetlbfs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/hugetlbfs/inode.c +1 -1
@@ -77,7 +77,7 @@ enum hugetlb_param {static const struct fs_parameter_spec hugetlb_fs_parameters[] = {fsparam_u32 ("gid" , Opt_gid),fsparam_string ("min_size" , Opt_min_size), -fsparam_u32 ("mode" , Opt_mode), +fsparam_u32oct ("mode" , Opt_mode),fsparam_string ("nr_inodes" , Opt_nr_inodes),fsparam_string ("pagesize" , Opt_pagesize),fsparam_string ("size" , Opt_size),
Greg Kroah-Hartman
maintainerPATCH 203/223 rbd: dont hold lock_rwsem while running_list is being drained
In reply to Greg Kroah-HartmanFrom: Ilya Dryomov <[email protected]>
commit ed9eb71085ecb7ded9a5118cec2ab70667cc7350 upstream.
Currently rbd_quiesce_lock() holds lock_rwsem for read while blocking on releasing_wait completion. On the I/O completion side, each image request also needs to take lock_rwsem for read. Because rw_semaphore implementation doesn't allow new readers after a writer has indicated interest in the lock, this can result in a deadlock if something that needs to take lock_rwsem for write gets involved. For example:
1. watch error occurs
2. rbd_watch_errcb() takes lock_rwsem for write, clears owner_cid and releases lock_rwsem
3. after reestablishing the watch, rbd_reregister_watch() takes lock_rwsem for write and calls rbd_reacquire_lock()
4. rbd_quiesce_lock() downgrades lock_rwsem to for read and blocks on releasing_wait until running_list becomes empty
5. another watch error occurs
6. rbd_watch_errcb() blocks trying to take lock_rwsem for write
7. no in-flight image request can complete and delete itself from running_list because lock_rwsem won't be granted anymore
A similar scenario can occur with "lock has been acquired" and "lock has been released" notification handers which also take lock_rwsem for write to update owner_cid.
We don't actually get anything useful from sitting on lock_rwsem in rbd_quiesce_lock() -- owner_cid updates certainly don't need to be synchronized with. In fact the whole owner_cid tracking logic could probably be removed from the kernel client because we don't support proxied maintenance operations.
Cc: [email protected] # 5.3+
URL: https://tracker.ceph.com/issues/42757
--- drivers/block/rbd.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-)
drivers/block/rbd.c +5 -7
@@ -4100,8 +4100,6 @@ again:static bool rbd_quiesce_lock (struct rbd_device *rbd_dev) { -bool need_wait; -dout ("%s rbd_dev %p\n" , __func__, rbd_dev);lockdep_assert_held_write (&rbd_dev->lock_rwsem);
@@ -4113,11 +4111,11 @@ static bool rbd_quiesce_lock(struct rbd_*/ rbd_dev->lock_state =RBD_LOCK_STATE_RELEASING ;rbd_assert (!completion_done (&rbd_dev->releasing_wait)); - need_wait = !list_empty (&rbd_dev->running_list); -downgrade_write (&rbd_dev->lock_rwsem); -if (need_wait) -wait_for_completion (&rbd_dev->releasing_wait); -up_read (&rbd_dev->lock_rwsem); +if (list_empty (&rbd_dev->running_list)) +return true; + +up_write (&rbd_dev->lock_rwsem); +wait_for_completion (&rbd_dev->releasing_wait);down_write (&rbd_dev->lock_rwsem);if (rbd_dev->lock_state !=RBD_LOCK_STATE_RELEASING )
Greg Kroah-Hartman
maintainerPATCH 204/223 rbd: always kick acquire on "acquired" and "released" notifications
In reply to Greg Kroah-HartmanFrom: Ilya Dryomov <[email protected]>
commit 8798d070d416d18a75770fc19787e96705073f43 upstream.
Skipping the "lock has been released" notification if the lock owner is not what we expect based on owner_cid can lead to I/O hangs. One example is our own notifications: because owner_cid is cleared in rbd_unlock(), when we get our own notification it is processed as unexpected/duplicate and maybe_kick_acquire() isn't called. If a peer that requested the lock then doesn't go through with acquiring it, I/O requests that came in while the lock was being quiesced would be stalled until another I/O request is submitted and kicks acquire from rbd_img_exclusive_lock().
This makes the comment in rbd_release_lock() actually true: prior to this change the canceled work was being requeued in response to the "lock has been acquired" notification from rbd_handle_acquired_lock().
--- drivers/block/rbd.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-)
drivers/block/rbd.c +7 -13
@@ -4201,15 +4201,11 @@ static void rbd_handle_acquired_lock(strif (!rbd_cid_equal (&cid, &rbd_empty_cid)) {down_write (&rbd_dev->lock_rwsem);if (rbd_cid_equal (&cid, &rbd_dev->owner_cid)) { -/* -* we already know that the remote client is -* the owner -*/ -up_write (&rbd_dev->lock_rwsem); -return ; +dout ("%s rbd_dev %p cid %llu-%llu == owner_cid\n" , + __func__, rbd_dev, cid.gid, cid.handle); + }else { +rbd_set_owner_cid (rbd_dev, &cid); } - -rbd_set_owner_cid (rbd_dev, &cid);downgrade_write (&rbd_dev->lock_rwsem); }else {down_read (&rbd_dev->lock_rwsem);
@@ -4234,14 +4230,12 @@ static void rbd_handle_released_lock(strif (!rbd_cid_equal (&cid, &rbd_empty_cid)) {down_write (&rbd_dev->lock_rwsem);if (!rbd_cid_equal (&cid, &rbd_dev->owner_cid)) { -dout ("%s rbd_dev %p unexpected owner, cid %llu-%llu != owner_cid %llu-%llu\n" , +dout ("%s rbd_dev %p cid %llu-%llu != owner_cid %llu-%llu\n" , __func__, rbd_dev, cid.gid, cid.handle, rbd_dev->owner_cid.gid, rbd_dev->owner_cid.handle); -up_write (&rbd_dev->lock_rwsem); -return ; + }else { +rbd_set_owner_cid (rbd_dev, &rbd_empty_cid); } - -rbd_set_owner_cid (rbd_dev, &rbd_empty_cid);downgrade_write (&rbd_dev->lock_rwsem); }else {down_read (&rbd_dev->lock_rwsem);
Greg Kroah-Hartman
maintainerPATCH 205/223 misc: eeprom: at24: Always append device id even if label property is set.
In reply to Greg Kroah-HartmanFrom: Jérôme Glisse <[email protected]>
commit c36748ac545421d94a5091c754414c0f3664bf10 upstream.
We need to append device id even if eeprom have a label property set as some platform can have multiple eeproms with same label and we can not register each of those with same label. Failing to register those eeproms trigger cascade failures on such platform (system is no longer working).
This fix regression on such platform introduced with 4e302c3b568e
--- drivers/misc/eeprom/at24.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-)
drivers/misc/eeprom/at24.c +7 -10
@@ -714,23 +714,20 @@ static int at24_probe(struct i2c_client }/* -* If the 'label' property is not present for the AT24 EEPROM, -* then nvmem_config.id is initialised to NVMEM_DEVID_AUTO, -* and this will append the 'devid' to the name of the NVMEM -* device. This is purely legacy and the AT24 driver has always -* defaulted to this. However, if the 'label' property is -* present then this means that the name is specified by the -* firmware and this name should be used verbatim and so it is -* not necessary to append the 'devid'. +* We initialize nvmem_config.id to NVMEM_DEVID_AUTO even if the +* label property is set as some platform can have multiple eeproms +* with same label and we can not register each of those with same +* label. Failing to register those eeproms trigger cascade failure +* on such platform. */ + nvmem_config.id =NVMEM_DEVID_AUTO ; +if (device_property_present (dev,"label" )) { - nvmem_config.id =NVMEM_DEVID_NONE ; err =device_property_read_string (dev,"label" , &nvmem_config.name);if (err)return err; }else { - nvmem_config.id =NVMEM_DEVID_AUTO ; nvmem_config.name =dev_name (dev); }
Greg Kroah-Hartman
maintainerPATCH 206/223 nds32: fix up stack guard gap
In reply to Greg Kroah-HartmanFrom: Greg Kroah-Hartman <[email protected]>
commit c453db6cd96418c79702eaf38259002755ab23ff upstream.
Commit 1be7107fbe18 ("mm: larger stack guard gap, between vmas") fixed up all architectures to deal with the stack guard gap. But when nds32 was added to the tree, it forgot to do the same thing.
Resolve this by properly fixing up the nsd32's version of arch_get_unmapped_area()
--- arch/nds32/mm/mmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/nds32/mm/mmap.c +1 -1
@@ -59,7 +59,7 @@ arch_get_unmapped_area(struct file *filp vma =find_vma (mm, addr);if (TASK_SIZE - len >= addr && - (!vma || addr + len <= vma->vm_start)) + (!vma || addr + len <=vm_start_gap (vma)))return addr; }
Greg Kroah-Hartman
maintainerPATCH 207/223 driver core: Prevent warning when removing a device link from unregistered consumer
In reply to Greg Kroah-HartmanFrom: Adrian Hunter <[email protected]>
commit e64daad660a0c9ace3acdc57099fffe5ed83f977 upstream.
sysfs_remove_link() causes a warning if the parent directory does not exist. That can happen if the device link consumer has not been registered. So do not attempt sysfs_remove_link() in that case.
--- drivers/base/core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/base/core.c +4 -2
@@ -574,8 +574,10 @@ static void devlink_remove_symlinks(strureturn ; } -snprintf (buf, len,"supplier:%s:%s" ,dev_bus_name (sup),dev_name (sup)); -sysfs_remove_link (&con->kobj, buf); +if (device_is_registered (con)) { +snprintf (buf, len,"supplier:%s:%s" ,dev_bus_name (sup),dev_name (sup)); +sysfs_remove_link (&con->kobj, buf); + }snprintf (buf, len,"consumer:%s:%s" ,dev_bus_name (con),dev_name (con));sysfs_remove_link (&sup->kobj, buf);kfree (buf);
Greg Kroah-Hartman
maintainerPATCH 208/223 Revert "drm/i915: Propagate errors on awaiting already signaled fences"
In reply to Greg Kroah-HartmanFrom: Jason Ekstrand <[email protected]>
commit 3761baae908a7b5012be08d70fa553cc2eb82305 upstream.
This reverts commit 9e31c1fe45d555a948ff66f1f0e3fe1f83ca63f7. Ever since that commit, we've been having issues where a hang in one client can propagate to another. In particular, a hang in an app can propagate to the X server which causes the whole desktop to lock up.
Error propagation along fences sound like a good idea, but as your bug shows, surprising consequences, since propagating errors across security boundaries is not a good thing.
What we do have is track the hangs on the ctx, and report information to userspace using RESET_STATS. That's how arb_robustness works. Also, if my understanding is still correct, the EIO from execbuf is when your context is banned (because not recoverable or too many hangs). And in all these cases it's up to userspace to figure out what is all impacted and should be reported to the application, that's not on the kernel to guess and automatically propagate.
What's more, we're also building more features on top of ctx error reporting with RESET_STATS ioctl: Encrypted buffers use the same, and the userspace fence wait also relies on that mechanism. So it is the path going forward for reporting gpu hangs and resets to userspace.
So all together that's why I think we should just bury this idea again as not quite the direction we want to go to, hence why I think the revert is the right option here.
For backporters: Please note that you _must_ have a backport of
https://lore.kernel.org/dri-devel/[email protected]/
for otherwise backporting just this patch opens up a security bug.
v2: Augment commit message. Also restore Jason's sob that I accidentally lost.
v3: Add a note for backporters
--- drivers/gpu/drm/i915/i915_request.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)
drivers/gpu/drm/i915/i915_request.c +2 -6
@@ -1426,10 +1426,8 @@ i915_request_await_execution(struct i915 do { fence = *child++; - if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) { - i915_sw_fence_set_error_once(&rq->submit, fence->error); + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) continue; - } if (fence->context == rq->fence.context) continue;
@@ -1527,10 +1525,8 @@ i915_request_await_dma_fence(struct i915 do { fence = *child++; - if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) { - i915_sw_fence_set_error_once(&rq->submit, fence->error); + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) continue; - } /* * Requests on the same timeline are explicitly ordered, along
Greg Kroah-Hartman
maintainerPATCH 209/223 drm: Return -ENOTTY for non-drm ioctls
In reply to Greg Kroah-HartmanFrom: Charles Baylis <[email protected]>
commit 3abab27c322e0f2acf981595aa8040c9164dc9fb upstream.
drm: Return -ENOTTY for non-drm ioctls
Return -ENOTTY from drm_ioctl() when userspace passes in a cmd number which doesn't relate to the drm subsystem.
Glibc uses the TCGETS ioctl to implement isatty(), and without this change isatty() returns it incorrectly returns true for drm devices.
To test run this command:
$ if [ -t 0 ]; then echo is a tty; fi < /dev/dri/card0 which shows "is a tty" without this patch.
This may also modify memory which the userspace application is not expecting.
--- drivers/gpu/drm/drm_ioctl.c | 3 +++ include/drm/drm_ioctl.h | 1 + 2 files changed, 4 insertions(+)
drivers/gpu/drm/drm_ioctl.c +3 -0
@@ -827,6 +827,9 @@ long drm_ioctl(struct file *filp,if (drm_dev_is_unplugged (dev))return -ENODEV ; +if (DRM_IOCTL_TYPE (cmd) !=DRM_IOCTL_BASE ) +return -ENOTTY ; + is_driver_ioctl = nr >=DRM_COMMAND_BASE && nr <DRM_COMMAND_END ;if (is_driver_ioctl) {
include/drm/drm_ioctl.h +1 -0
@@ -68,6 +68,7 @@ typedef int drm_ioctl_compat_t(struct fi unsigned long arg);#define DRM_IOCTL_NR (n) _IOC_NR(n) +#define DRM_IOCTL_TYPE (n) _IOC_TYPE(n)#define DRM_MAJOR 226/**
Greg Kroah-Hartman
maintainerPATCH 210/223 drm/amdgpu: update gc golden setting for dimgrey_cavefish
In reply to Greg Kroah-HartmanFrom: Tao Zhou <[email protected]>
commit cfe4e8f00f8f19ba305800f64962d1949ab5d4ca upstream.
Update gc_10_3_4 golden setting.
--- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +1 -0
@@ -3411,6 +3411,7 @@ static const struct soc15_reg_golden golSOC15_REG_GOLDEN_VALUE (GC ,0 , mmSQ_PERFCOUNTER7_SELECT,0xf0f001ff ,0x00000000 ),SOC15_REG_GOLDEN_VALUE (GC ,0 , mmSQ_PERFCOUNTER8_SELECT,0xf0f001ff ,0x00000000 ),SOC15_REG_GOLDEN_VALUE (GC ,0 , mmSQ_PERFCOUNTER9_SELECT,0xf0f001ff ,0x00000000 ), +SOC15_REG_GOLDEN_VALUE (GC ,0 , mmSX_DEBUG_1,0x00010000 ,0x00010020 ),SOC15_REG_GOLDEN_VALUE (GC ,0 , mmTA_CNTL_AUX,0x01030000 ,0x01030000 ),SOC15_REG_GOLDEN_VALUE (GC ,0 , mmUTCL1_CTRL,0x03a00000 ,0x00a00000 ),SOC15_REG_GOLDEN_VALUE (GC ,0 , mmLDS_CONFIG,0x00000020 ,0x00000020 )
Greg Kroah-Hartman
maintainerPATCH 211/223 drm/amdgpu: update the golden setting for vangogh
In reply to Greg Kroah-HartmanFrom: Xiaojian Du <[email protected]>
commit 4fff6fbca12524358a32e56f125ae738141f62b4 upstream.
This patch is to update the golden setting for vangogh.
--- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +1 -0
@@ -3369,6 +3369,7 @@ static const struct soc15_reg_golden golSOC15_REG_GOLDEN_VALUE (GC ,0 , mmPA_SC_ENHANCE_2,0xffffffbf ,0x00000020 ),SOC15_REG_GOLDEN_VALUE (GC ,0 , mmSPI_CONFIG_CNTL_1_Vangogh,0xffffffff ,0x00070103 ),SOC15_REG_GOLDEN_VALUE (GC ,0 , mmSQG_CONFIG,0x000017ff ,0x00001000 ), +SOC15_REG_GOLDEN_VALUE (GC ,0 , mmSX_DEBUG_1,0x00010000 ,0x00010020 ),SOC15_REG_GOLDEN_VALUE (GC ,0 , mmTA_CNTL_AUX,0xfff7ffff ,0x01030000 ),SOC15_REG_GOLDEN_VALUE (GC ,0 , mmUTCL1_CTRL,0xffffffff ,0x00400000 ), SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x00000fff, 0x000000ff),
Greg Kroah-Hartman
maintainerPATCH 212/223 drm/amdgpu: update golden setting for sienna_cichlid
In reply to Greg Kroah-HartmanFrom: Likun Gao <[email protected]>
commit 3e94b5965e624f7e6d8dd18eb8f3bf2bb99ba30d upstream.
Update GFX golden setting for sienna_cichlid.
--- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +1 -0
@@ -3290,6 +3290,7 @@ static const struct soc15_reg_golden golSOC15_REG_GOLDEN_VALUE (GC ,0 , mmSQ_PERFCOUNTER7_SELECT,0xf0f001ff ,0x00000000 ),SOC15_REG_GOLDEN_VALUE (GC ,0 , mmSQ_PERFCOUNTER8_SELECT,0xf0f001ff ,0x00000000 ),SOC15_REG_GOLDEN_VALUE (GC ,0 , mmSQ_PERFCOUNTER9_SELECT,0xf0f001ff ,0x00000000 ), +SOC15_REG_GOLDEN_VALUE (GC ,0 , mmSX_DEBUG_1,0x00010000 ,0x00010020 ),SOC15_REG_GOLDEN_VALUE (GC ,0 , mmTA_CNTL_AUX,0xfff7ffff ,0x01030000 ), SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0xffbfffff, 0x00a00000) };
Greg Kroah-Hartman
maintainerPATCH 213/223 spi: spi-cadence-quadspi: Revert "Fix division by zero warning"
In reply to Greg Kroah-HartmanFrom: Yoshitaka Ikeda <[email protected]>
commit 0ccfd1ba84a4503b509250941af149e9ebd605ca upstream.
Revert to change to a better code.
This reverts commit 55cef88bbf12f3bfbe5c2379a8868a034707e755.
--- drivers/spi/spi-cadence-quadspi.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
drivers/spi/spi-cadence-quadspi.c +4 -6
@@ -307,13 +307,11 @@ static unsigned int cqspi_calc_rdreg(strstatic unsigned int cqspi_calc_dummy (const struct spi_mem_op *op,bool dtr) { -unsigned int dummy_clk =0 ; +unsigned int dummy_clk; -if (op->dummy.buswidth && op->dummy.nbytes) { - dummy_clk = op->dummy.nbytes * (8 / op->dummy.buswidth); -if (dtr) - dummy_clk /=2 ; - } + dummy_clk = op->dummy.nbytes * (8 / op->dummy.buswidth); +if (dtr) + dummy_clk /=2 ;return dummy_clk; }
Greg Kroah-Hartman
maintainerPATCH 214/223 bonding: fix build issue
In reply to Greg Kroah-HartmanFrom: Mahesh Bandewar <[email protected]>
commit 5b69874f74cc5707edd95fcdaa757c507ac8af0f upstream.
The commit 9a5605505d9c (" bonding: Add struct bond_ipesc to manage SA") is causing following build error when XFRM is not selected in kernel config.
lld: error: undefined symbol: xfrm_dev_state_flush
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
referenced by bond_main.c:3453 (
drivers/net/bonding/bond_main.c:3453)
net/bonding/bond_main.o:(bond_netdev_event) in archivedrivers/built-in.a
--- drivers/net/bonding/bond_main.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/bonding/bond_main.c +2 -0
@@ -3442,7 +3442,9 @@ static int bond_master_netdev_event(unsireturn bond_event_changename (event_bond);case NETDEV_UNREGISTER :bond_remove_proc_entry (event_bond); +#ifdef CONFIG_XFRM_OFFLOAD xfrm_dev_state_flush (dev_net (bond_dev), bond_dev, true); +#endif /* CONFIG_XFRM_OFFLOAD */ break ;case NETDEV_REGISTER :bond_create_proc_entry (event_bond);
Greg Kroah-Hartman
maintainerPATCH 215/223 mptcp: fix masking a bool warning
In reply to Greg Kroah-HartmanFrom: Matthieu Baerts <[email protected]>
commit c4512c63b1193c73b3f09c598a6d0a7f88da1dd8 upstream.
Dan Carpenter reported an issue introduced in
commit fde56eea01f9 ("mptcp: refine mptcp_cleanup_rbuf") where a new boolean (ack_pending) is masked with 0x9.
This is not the intention to ignore values by using a boolean. This variable should not have a 'bool' type: we should keep the 'u8' to allow this comparison.
--- net/mptcp/protocol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/mptcp/protocol.c +1 -1
@@ -446,7 +446,7 @@ static void mptcp_subflow_cleanup_rbuf(sstatic bool mptcp_subflow_could_cleanup (const struct sock *ssk,bool rx_empty) {const struct inet_connection_sock *icsk =inet_csk (ssk); -bool ack_pending =READ_ONCE (icsk->icsk_ack.pending); +u8 ack_pending =READ_ONCE (icsk->icsk_ack.pending);const struct tcp_sock *tp =tcp_sk (ssk); return (ack_pending & ICSK_ACK_SCHED) &&
Greg Kroah-Hartman
maintainerPATCH 216/223 skbuff: Release nfct refcount on napi stolen or re-used skbs
In reply to Greg Kroah-HartmanFrom: Paul Blakey <[email protected]>
commit 8550ff8d8c75416e984d9c4b082845e57e560984 upstream.
When multiple SKBs are merged to a new skb under napi GRO, or SKB is re-used by napi, if nfct was set for them in the driver, it will not be released while freeing their stolen head state or on re-use.
Release nfct on napi's stolen or re-used SKBs, and in gro_list_prepare, check conntrack metadata diff.
--- net/core/dev.c | 13 +++++++++++++ net/core/skbuff.c | 1 + 2 files changed, 14 insertions(+)
net/core/dev.c +13 -0
@@ -5981,6 +5981,18 @@ static void gro_list_prepare(const struc diffs =memcmp (skb_mac_header (p),skb_mac_header (skb), maclen); + + diffs |=skb_get_nfct (p) ^skb_get_nfct (skb); + +if (!diffs) { +struct tc_skb_ext *skb_ext =skb_ext_find (skb,TC_SKB_EXT ); +struct tc_skb_ext *p_ext =skb_ext_find (p,TC_SKB_EXT ); + + diffs |= (!!p_ext) ^ (!!skb_ext); +if (!diffs &&unlikely (skb_ext)) + diffs |= p_ext->chain ^ skb_ext->chain; + } +NAPI_GRO_CB (p)->same_flow = !diffs; } }
@@ -6245,6 +6257,7 @@ static void napi_reuse_skb(struct napi_sskb_shinfo (skb)->gso_type =0 ; skb->truesize =SKB_TRUESIZE (skb_end_offset (skb));skb_ext_reset (skb); +nf_reset_ct (skb); napi->skb = skb; }
net/core/skbuff.c +1 -0
@@ -939,6 +939,7 @@ void __kfree_skb_defer(struct sk_buff *svoid napi_skb_free_stolen_head (struct sk_buff *skb) { +nf_reset_ct (skb);skb_dst_drop (skb);skb_ext_put (skb);napi_skb_cache_put (skb);
Greg Kroah-Hartman
maintainerPATCH 217/223 ARM: multi_v7_defconfig: Make NOP_USB_XCEIV driver built-in
In reply to Greg Kroah-HartmanFrom: Stefan Wahren <[email protected]>
commit ab37a7a890c1176144a4c66ff3d51ef2c20ed486 upstream.
The usage of usb-nop-xceiv PHY on Raspberry Pi boards with BCM283x has been a "regression source" a lot of times. The last case is breakage of USB mass storage boot has been commit e590474768f1 ("driver core: Set fw_devlink=on by default") for multi_v7_defconfig. As long as NOP_USB_XCEIV is configured as module, the dwc2 USB driver defer probing endlessly and prevent booting from USB mass storage device. So make the driver built-in as in bcm2835_defconfig and arm64/defconfig.
--- arch/arm/configs/multi_v7_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/configs/multi_v7_defconfig +1 -1
@@ -821,7 +821,7 @@ CONFIG_USB_ISP1760=y CONFIG_USB_HSIC_USB3503=y CONFIG_AB8500_USB=y CONFIG_KEYSTONE_USB_PHY=m -CONFIG_NOP_USB_XCEIV=m +CONFIG_NOP_USB_XCEIV=y CONFIG_AM335X_PHY_USB=m CONFIG_TWL6030_USB=m CONFIG_USB_GPIO_VBUS=y
Greg Kroah-Hartman
maintainerPATCH 218/223 Documentation: Fix intiramfs script name
In reply to Greg Kroah-HartmanFrom: Robert Richter <[email protected]>
commit 5e60f363b38fd40e4d8838b5d6f4d4ecee92c777 upstream.
Documentation was not changed when renaming the script in commit 80e715a06c2d ("initramfs: rename gen_initramfs_list.sh to gen_initramfs.sh"). Fixing this.
Basically does:
$ sed -i -e s/gen_initramfs_list.sh/gen_initramfs.sh/g $(git grep -l gen_initramfs_list.sh)
--- Documentation/driver-api/early-userspace/early_userspace_support.rst | 8 ++++---- Documentation/filesystems/ramfs-rootfs-initramfs.rst | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-)
Documentation/driver-api/early-userspace/early_userspace_support.rst +4 -4
@@ -69,17 +69,17 @@ early userspace image can be built by an As a technical note, when directories and files are specified, the entire CONFIG_INITRAMFS_SOURCE is passed to -usr/gen_initramfs_list.sh. This means that CONFIG_INITRAMFS_SOURCE +usr/gen_initramfs.sh. This means that CONFIG_INITRAMFS_SOURCE can really be interpreted as any legal argument to -gen_initramfs_list.sh. If a directory is specified as an argument then +gen_initramfs.sh. If a directory is specified as an argument then the contents are scanned, uid/gid translation is performed, and usr/gen_init_cpio file directives are output. If a directory is -specified as an argument to usr/gen_initramfs_list.sh then the +specified as an argument to usr/gen_initramfs.sh then the contents of the file are simply copied to the output. All of the output directives from directory scanning and file contents copying are processed by usr/gen_init_cpio. -See also 'usr/gen_initramfs_list.sh -h'. +See also 'usr/gen_initramfs.sh -h'. Where's this all leading? =========================
Documentation/filesystems/ramfs-rootfs-initramfs.rst +1 -1
@@ -170,7 +170,7 @@ Documentation/driver-api/early-userspace The kernel does not depend on external cpio tools. If you specify a directory instead of a configuration file, the kernel's build infrastructure creates a configuration file from that directory (usr/Makefile calls -usr/gen_initramfs_list.sh), and proceeds to package up that directory +usr/gen_initramfs.sh), and proceeds to package up that directory using the config file (by feeding it to usr/gen_init_cpio, which is created from usr/gen_init_cpio.c). The kernel's build-time cpio creation code is entirely self-contained, and the kernel's boot-time extractor is also
Greg Kroah-Hartman
maintainerPATCH 219/223 arm64: entry: fix KCOV suppression
In reply to Greg Kroah-HartmanFrom: Mark Rutland <[email protected]>
commit e6f85cbeb23bd74b8966cf1f15bf7d01399ff625 upstream.
We suppress KCOV for entry.o rather than entry-common.o. As entry.o is built from entry.S, this is pointless, and permits instrumentation of entry-common.o, which is built from entry-common.c.
Fix the Makefile to suppress KCOV for entry-common.o, as we had intended to begin with. I've verified with objdump that this is working as expected.
--- arch/arm64/kernel/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/kernel/Makefile +1 -1
@@ -17,7 +17,7 @@ CFLAGS_syscall.o += -fno-stack-protector # It's not safe to invoke KCOV when portions of the kernel environment aren't # available or are out-of-sync with HW state. Since `noinstr` doesn't always # inhibit KCOV instrumentation, disable it for the entire compilation unit. -KCOV_INSTRUMENT_entry.o := n +KCOV_INSTRUMENT_entry-common.o := n # Object file lists. obj-y := debug-monitors.o entry.o irq.o fpsimd.o \
Greg Kroah-Hartman
maintainerPATCH 220/223 perf inject: Close inject.output on exit
In reply to Greg Kroah-HartmanFrom: Riccardo Mancini <[email protected]>
commit 02e6246f5364d5260a6ea6f92ab6f409058b162f upstream.
ASan reports a memory leak when running:
# perf test "83: Zstd perf.data compression/decompression"
which happens inside 'perf inject'.
The bug is caused by inject.output never being closed.
This patch adds the missing perf_data__close().
--- tools/perf/builtin-inject.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
tools/perf/builtin-inject.c +6 -2
@@ -908,8 +908,10 @@ int cmd_inject(int argc, const char **ar data.path = inject.input_name; inject.session =perf_session__new (&data, inject.output.is_pipe, &inject.tool); -if (IS_ERR (inject.session)) -return PTR_ERR (inject.session); +if (IS_ERR (inject.session)) { + ret =PTR_ERR (inject.session); + goto out_close_output; + }if (zstd_init (&(inject.session->zstd_data),0 ) <0 )pr_warning ("Decompression initialization failed.\n" );
@@ -951,5 +953,7 @@ int cmd_inject(int argc, const char **ar out_delete:zstd_fini (&(inject.session->zstd_data));perf_session__delete (inject.session); +out_close_output: +perf_data__close (&inject.output);return ret; }
Greg Kroah-Hartman
maintainerPATCH 221/223 drm/i915/gvt: Clear d3_entered on elsp cmd submission.
In reply to Greg Kroah-HartmanFrom: Colin Xu <[email protected]>
commit c90b4503ccf42d9d367e843c223df44aa550e82a upstream.
d3_entered flag is used to mark for vgpu_reset a previous power transition from D3->D0, typically for VM resume from S3, so that gvt could skip PPGTT invalidation in current vgpu_reset during resuming.
In case S0ix exit, although there is D3->D0, guest driver continue to use vgpu as normal, with d3_entered set, until next shutdown/reboot or power transition.
If a reboot follows a S0ix exit, device power state transite as:D0->D3->D0->D0(reboot), while system power state transites as:S0->S0 (reboot). There is no vgpu_reset until D0(reboot), thus d3_entered won't be cleared, the vgpu_reset will skip PPGTT invalidation however those PPGTT entries are no longer valid. Err appears like:
gvt: vgpu 2: vfio_pin_pages failed for gfn 0xxxxx, ret -22
gvt: vgpu 2: fail: spt xxxx guest entry 0xxxxx type 2
gvt: vgpu 2: fail: shadow page xxxx guest entry 0xxxxx type 2.
Give gvt a chance to clear d3_entered on elsp cmd submission so that the states before & after S0ix enter/exit are consistent.
--- drivers/gpu/drm/i915/gvt/handlers.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
drivers/gpu/drm/i915/gvt/handlers.c +15 -0
@@ -1977,6 +1977,21 @@ static int elsp_mmio_write(struct intel_if (drm_WARN_ON (&i915->drm, !engine))return -EINVAL ; +/* +* Due to d3_entered is used to indicate skipping PPGTT invalidation on +* vGPU reset, it's set on D0->D3 on PCI config write, and cleared after +* vGPU reset if in resuming. +* In S0ix exit, the device power state also transite from D3 to D0 as +* S3 resume, but no vGPU reset (triggered by QEMU devic model). After +* S0ix exit, all engines continue to work. However the d3_entered +* remains set which will break next vGPU reset logic (miss the expected +* PPGTT invalidation). +* Engines can only work in D0. Thus the 1st elsp write gives GVT a +* chance to clear d3_entered. +*/ +if (vgpu->d3_entered) + vgpu->d3_entered = false; + execlist = &vgpu->submission.execlist[engine->id]; execlist->elsp_dwords.data[3 - execlist->elsp_dwords.index] = data;
Greg Kroah-Hartman
maintainerPATCH 222/223 spi: spi-cadence-quadspi: Fix division by zero warning - try2
In reply to Greg Kroah-HartmanFrom: Yoshitaka Ikeda <[email protected]>
commit 0e85ee897858b1c7a5de53f496d016899d9639c5 upstream.
Fix below division by zero warning:
- The reason for dividing by zero is because the dummy bus width is zero, but if the dummy n bytes is zero, it indicates that there is no data transfer, so we can just return zero without doing any calculations.
[ 0.795337] Division by zero in kernel. : [ 0.834051] [<807fd40c>] (__div0) from [<804e1acc>] (Ldiv0+0x8/0x10) [ 0.839097] [<805f0710>] (cqspi_exec_mem_op) from [<805edb4c>] (spi_mem_exec_op+0x3b0/0x3f8)
--- drivers/spi/spi-cadence-quadspi.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/spi/spi-cadence-quadspi.c +3 -0
@@ -309,6 +309,9 @@ static unsigned int cqspi_calc_dummy(con {unsigned int dummy_clk; +if (!op->dummy.nbytes) +return 0 ; + dummy_clk = op->dummy.nbytes * (8 / op->dummy.buswidth);if (dtr) dummy_clk /=2 ;
Greg Kroah-Hartman
maintainerPATCH 223/223 sfc: ensure correct number of XDP queues
In reply to Greg Kroah-HartmanFrom: Íñigo Huguet <[email protected]>
[ Upstream commit 788bc000d4c2f25232db19ab3a0add0ba4e27671 ]
Commit 99ba0ea616aa ("sfc: adjust efx->xdp_tx_queue_count with the real number of initialized queues") intended to fix a problem caused by a round up when calculating the number of XDP channels and queues. However, this was not the real problem. The real problem was that the number of XDP TX queues had been reduced to half in
commit e26ca4b53582 ("sfc: reduce the number of requested xdp ev queues"), but the variable xdp_tx_queue_count had remained the same.
Once the correct number of XDP TX queues is created again in the previous patch of this series, this also can be reverted since the error doesn't actually exist.
Only in the case that there is a bug in the code we can have different values in xdp_queue_number and efx->xdp_tx_queue_count. Because of this, and per Edward Cree's suggestion, I add instead a WARN_ON to catch if it happens again in the future.
Note that the number of allocated queues can be higher than the number of used ones due to the round up, as explained in the existing comment in the code. That's why we also have to stop increasing xdp_queue_number beyond efx->xdp_tx_queue_count.
--- drivers/net/ethernet/sfc/efx_channels.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
drivers/net/ethernet/sfc/efx_channels.c +8 -7
@@ -892,18 +892,20 @@ int efx_set_channels(struct efx_nic *efx)if (efx_channel_is_xdp_tx (channel)) {efx_for_each_channel_tx_queue (tx_queue, channel) { tx_queue->queue = next_queue++; -netif_dbg (efx, drv, efx->net_dev,"Channel %u TXQ %u is XDP %u, HW %u\n" , - channel->channel, tx_queue->label, - xdp_queue_number, tx_queue->queue); +/* We may have a few left-over XDP TX * queues owing to xdp_tx_queue_count * not dividing evenly by EFX_MAX_TXQ_PER_CHANNEL. * We still allocate and probe those * TXQs, but never use them. */ -if (xdp_queue_number < efx->xdp_tx_queue_count) +if (xdp_queue_number < efx->xdp_tx_queue_count) { +netif_dbg (efx, drv, efx->net_dev,"Channel %u TXQ %u is XDP %u, HW %u\n" , + channel->channel, tx_queue->label, + xdp_queue_number, tx_queue->queue); efx->xdp_tx_queues[xdp_queue_number] = tx_queue; - xdp_queue_number++; + xdp_queue_number++; + } } }else {efx_for_each_channel_tx_queue (tx_queue, channel) {
@@ -915,8 +917,7 @@ int efx_set_channels(struct efx_nic *efx) } } } -if (xdp_queue_number) - efx->xdp_tx_queue_count = xdp_queue_number; +WARN_ON (xdp_queue_number != efx->xdp_tx_queue_count); rc =netif_set_real_num_tx_queues (efx->net_dev, efx->n_tx_channels);if (rc)
Signature · 1 line
2.30.2
Hello!
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.13.6 release. There are 223 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 28 Jul 2021 15:38:12 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.13.6-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.13.y
and the diffstat can be found below.thanks,
greg k-h
Build regressions detected across plenty of architectures and configurations:
/builds/linux/net/core/dev.c: In function 'gro_list_prepare':
/builds/linux/net/core/dev.c:5988:72: error: 'TC_SKB_EXT' undeclared (first use in this function)
5988 | struct tc_skb_ext *skb_ext = skb_ext_find(skb, TC_SKB_EXT);
| ^~~~~~~~~~
/builds/linux/net/core/dev.c:5988:72: note: each undeclared identifier is reported only once for each function it appears in /builds/linux/net/core/dev.c:5993:47: error: invalid use of undefined type 'struct tc_skb_ext'
5993 | diffs |= p_ext->chain ^ skb_ext->chain;
| ^~
/builds/linux/net/core/dev.c:5993:64: error: invalid use of undefined type 'struct tc_skb_ext'
5993 | diffs |= p_ext->chain ^ skb_ext->chain;
| ^~
make[3]: *** [/builds/linux/scripts/Makefile.build:273: net/core/dev.o] Error 1
make[3]: Target '__build' not remade because of errors.
make[2]: *** [/builds/linux/scripts/Makefile.build:516: net/core] Error 2
make[2]: Target '__build' not remade because of errors.
make[1]: *** [/builds/linux/Makefile:1853: net] Error 2
make[1]: Target '__all' not remade because of errors.
make: *** [Makefile:220: __sub-make] Error 2
Here's a summary:
* arc: 10 total, 4 passed, 6 failed
* arm: 193 total, 18 passed, 175 failed
* arm64: 27 total, 12 passed, 15 failed
* dragonboard-410c: 1 total, 0 passed, 1 failed
* hi6220-hikey: 1 total, 0 passed, 1 failed
* i386: 26 total, 12 passed, 14 failed
* mips: 45 total, 15 passed, 30 failed
* parisc: 9 total, 6 passed, 3 failed
* powerpc: 27 total, 6 passed, 21 failed
* riscv: 21 total, 14 passed, 7 failed
* s390: 18 total, 12 passed, 6 failed
* sh: 18 total, 6 passed, 12 failed
* sparc: 9 total, 6 passed, 3 failed
* x15: 1 total, 0 passed, 1 failed
* x86: 1 total, 0 passed, 1 failed
* x86_64: 27 total, 12 passed, 15 failed
All failed, except allnoconfig, tinyconfig, and a few others here and there.
Same applies for 5.10.
Greetings!
Daniel Díaz
[email protected]
Greg Kroah-Hartman
maintainerQuoted 61 lines · Daniel Díaz
Hello!
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.13.6 release. There are 223 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 28 Jul 2021 15:38:12 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.13.6-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.13.y
and the diffstat can be found below.thanks,
greg k-h
Build regressions detected across plenty of architectures and configurations:
/builds/linux/net/core/dev.c: In function '
gro_list_prepare':
/builds/linux/net/core/dev.c:5988:72: error: 'TC_SKB_EXT' undeclared (first use in this function)
5988 | structtc_skb_ext*skb_ext=skb_ext_find(skb, TC_SKB_EXT);
| ^~~~~~~~~~
/builds/linux/net/core/dev.c:5988:72: note: each undeclared identifier is reported only once for each function it appears in /builds/linux/net/core/dev.c:5993:47: error: invalid use of undefined type 'structtc_skb_ext'
5993 | diffs |=p_ext->chain^skb_ext->chain;
| ^~
/builds/linux/net/core/dev.c:5993:64: error: invalid use of undefined type 'structtc_skb_ext'
5993 | diffs |=p_ext->chain^skb_ext->chain;
| ^~
make[3]: *** [/builds/linux/scripts/Makefile.build:273:net/core/dev.o] Error 1
make[3]: Target '__build' not remade because of errors.
make[2]: *** [/builds/linux/scripts/Makefile.build:516: net/core] Error 2
make[2]: Target '__build' not remade because of errors.
make[1]: *** [/builds/linux/Makefile:1853: net] Error 2
make[1]: Target '__all' not remade because of errors.
make: *** [Makefile:220: __sub-make] Error 2Here's a summary:
* arc: 10 total, 4 passed, 6 failed
* arm: 193 total, 18 passed, 175 failed
* arm64: 27 total, 12 passed, 15 failed
* dragonboard-410c: 1 total, 0 passed, 1 failed
* hi6220-hikey: 1 total, 0 passed, 1 failed
* i386: 26 total, 12 passed, 14 failed
* mips: 45 total, 15 passed, 30 failed
* parisc: 9 total, 6 passed, 3 failed
* powerpc: 27 total, 6 passed, 21 failed
* riscv: 21 total, 14 passed, 7 failed
* s390: 18 total, 12 passed, 6 failed
* sh: 18 total, 6 passed, 12 failed
* sparc: 9 total, 6 passed, 3 failed
* x15: 1 total, 0 passed, 1 failed
* x86: 1 total, 0 passed, 1 failed
*x86_64: 27 total, 12 passed, 15 failed
Quoted 3 lines
All failed, except allnoconfig, tinyconfig, and a few others here and there.
Same applies for 5.10.
Ah, I missed:
9615fe36b31d ("skbuff: Fix build with SKB extensions disabled")
will fix that and push out a 5.13.y and 5.10.y update now...
thanks,
greg k-h
Quoted 18 lines · Daniel Díaz
Hello!
Quoted 14 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.13.6 release. There are 223 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 28 Jul 2021 15:38:12 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.13.6-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.13.y
and the diffstat can be found below.
Quoted 5 lines
Quoted 3 lines
thanks,
greg k-h
Build regressions detected across plenty of architectures and configurations:
I was going to report the same but just noticed that Greg has pushed out -rc2.
Signature · 2 lines
Regards Sudip
Greg Kroah-Hartman
maintainerQuoted 19 lines · Sudip Mukherjee
Quoted 18 lines · Daniel Díaz
Hello!
Quoted 14 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.13.6 release. There are 223 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 28 Jul 2021 15:38:12 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.13.6-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.13.y
and the diffstat can be found below.
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
thanks,
greg k-h
Build regressions detected across plenty of architectures and configurations:
I was going to report the same but just noticed that Greg has pushed out -rc2.
I forgot to push it out last night, it's there now, sorry for the delay.
greg k-h
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.13.6 release. There are 223 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 28 Jul 2021 15:38:12 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.13.6-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.13.y
and the diffstat can be found below.thanks,
greg k-h
Tested rc2 against the Fedora build system (aarch64, armv7, ppc64le, s390x, x86_64), and boot tested x86_64. No regressions noted.
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.13.6 release. There are 223 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 28 Jul 2021 15:38:12 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.13.6-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.13.y
and the diffstat can be found below.thanks,
greg k-h
On ARCH_BRCMSTB using 32-bit and 64-bit ARM kernels, using -rc2:
Signature · 1 line
Florian
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.13.6 release. There are 223 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 28 Jul 2021 15:38:12 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.13.6-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.13.y
and the diffstat can be found below.thanks,
greg k-h
Compiled and booted on my test system. No dmesg regressions.
thanks,
-- Shuah