Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: dwc2: embed storage for reg backup in struct dwc2_hsotg

Register backup function can be called from atomic context. Instead
of using atomic memory pool, embed backup storage space in
struct dwc2_hsotg.

Also add a valid flag in each struct as NULL pointer can't be used as
the content validity check any more.

Acked-by: John Youn <johnyoun@synopsys.com>
Tested-by: Heiko Stuebner <heiko@sntech.de>
Tested-by: Doug Anderson <dianders@chromium.org>
Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@intel.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>

authored by

Mian Yousaf Kaukab and committed by
Felipe Balbi
cc1e204c b5a468a6

+21 -43
+15 -40
drivers/usb/dwc2/core.c
··· 72 72 dev_dbg(hsotg->dev, "%s\n", __func__); 73 73 74 74 /* Backup Host regs */ 75 - hr = hsotg->hr_backup; 76 - if (!hr) { 77 - hr = devm_kzalloc(hsotg->dev, sizeof(*hr), GFP_KERNEL); 78 - if (!hr) { 79 - dev_err(hsotg->dev, "%s: can't allocate host regs\n", 80 - __func__); 81 - return -ENOMEM; 82 - } 83 - 84 - hsotg->hr_backup = hr; 85 - } 75 + hr = &hsotg->hr_backup; 86 76 hr->hcfg = readl(hsotg->regs + HCFG); 87 77 hr->haintmsk = readl(hsotg->regs + HAINTMSK); 88 78 for (i = 0; i < hsotg->core_params->host_channels; ++i) ··· 80 90 81 91 hr->hprt0 = readl(hsotg->regs + HPRT0); 82 92 hr->hfir = readl(hsotg->regs + HFIR); 93 + hr->valid = true; 83 94 84 95 return 0; 85 96 } ··· 100 109 dev_dbg(hsotg->dev, "%s\n", __func__); 101 110 102 111 /* Restore host regs */ 103 - hr = hsotg->hr_backup; 104 - if (!hr) { 112 + hr = &hsotg->hr_backup; 113 + if (!hr->valid) { 105 114 dev_err(hsotg->dev, "%s: no host registers to restore\n", 106 115 __func__); 107 116 return -EINVAL; 108 117 } 118 + hr->valid = false; 109 119 110 120 writel(hr->hcfg, hsotg->regs + HCFG); 111 121 writel(hr->haintmsk, hsotg->regs + HAINTMSK); ··· 144 152 dev_dbg(hsotg->dev, "%s\n", __func__); 145 153 146 154 /* Backup dev regs */ 147 - dr = hsotg->dr_backup; 148 - if (!dr) { 149 - dr = devm_kzalloc(hsotg->dev, sizeof(*dr), GFP_KERNEL); 150 - if (!dr) { 151 - dev_err(hsotg->dev, "%s: can't allocate device regs\n", 152 - __func__); 153 - return -ENOMEM; 154 - } 155 - 156 - hsotg->dr_backup = dr; 157 - } 155 + dr = &hsotg->dr_backup; 158 156 159 157 dr->dcfg = readl(hsotg->regs + DCFG); 160 158 dr->dctl = readl(hsotg->regs + DCTL); ··· 177 195 dr->doeptsiz[i] = readl(hsotg->regs + DOEPTSIZ(i)); 178 196 dr->doepdma[i] = readl(hsotg->regs + DOEPDMA(i)); 179 197 } 180 - 198 + dr->valid = true; 181 199 return 0; 182 200 } 183 201 ··· 197 215 dev_dbg(hsotg->dev, "%s\n", __func__); 198 216 199 217 /* Restore dev regs */ 200 - dr = hsotg->dr_backup; 201 - if (!dr) { 218 + dr = &hsotg->dr_backup; 219 + if (!dr->valid) { 202 220 dev_err(hsotg->dev, "%s: no device registers to restore\n", 203 221 __func__); 204 222 return -EINVAL; 205 223 } 224 + dr->valid = false; 206 225 207 226 writel(dr->dcfg, hsotg->regs + DCFG); 208 227 writel(dr->dctl, hsotg->regs + DCTL); ··· 251 268 int i; 252 269 253 270 /* Backup global regs */ 254 - gr = hsotg->gr_backup; 255 - if (!gr) { 256 - gr = devm_kzalloc(hsotg->dev, sizeof(*gr), GFP_KERNEL); 257 - if (!gr) { 258 - dev_err(hsotg->dev, "%s: can't allocate global regs\n", 259 - __func__); 260 - return -ENOMEM; 261 - } 262 - 263 - hsotg->gr_backup = gr; 264 - } 271 + gr = &hsotg->gr_backup; 265 272 266 273 gr->gotgctl = readl(hsotg->regs + GOTGCTL); 267 274 gr->gintmsk = readl(hsotg->regs + GINTMSK); ··· 264 291 for (i = 0; i < MAX_EPS_CHANNELS; i++) 265 292 gr->dtxfsiz[i] = readl(hsotg->regs + DPTXFSIZN(i)); 266 293 294 + gr->valid = true; 267 295 return 0; 268 296 } 269 297 ··· 283 309 dev_dbg(hsotg->dev, "%s\n", __func__); 284 310 285 311 /* Restore global regs */ 286 - gr = hsotg->gr_backup; 287 - if (!gr) { 312 + gr = &hsotg->gr_backup; 313 + if (!gr->valid) { 288 314 dev_err(hsotg->dev, "%s: no global registers to restore\n", 289 315 __func__); 290 316 return -EINVAL; 291 317 } 318 + gr->valid = false; 292 319 293 320 writel(0xffffffff, hsotg->regs + GINTSTS); 294 321 writel(gr->gotgctl, hsotg->regs + GOTGCTL);
+6 -3
drivers/usb/dwc2/core.h
··· 492 492 u32 gdfifocfg; 493 493 u32 dtxfsiz[MAX_EPS_CHANNELS]; 494 494 u32 gpwrdn; 495 + bool valid; 495 496 }; 496 497 497 498 /** ··· 522 521 u32 doepctl[MAX_EPS_CHANNELS]; 523 522 u32 doeptsiz[MAX_EPS_CHANNELS]; 524 523 u32 doepdma[MAX_EPS_CHANNELS]; 524 + bool valid; 525 525 }; 526 526 527 527 /** ··· 540 538 u32 hcintmsk[MAX_EPS_CHANNELS]; 541 539 u32 hprt0; 542 540 u32 hfir; 541 + bool valid; 543 542 }; 544 543 545 544 /** ··· 708 705 struct work_struct wf_otg; 709 706 struct timer_list wkp_timer; 710 707 enum dwc2_lx_state lx_state; 711 - struct dwc2_gregs_backup *gr_backup; 712 - struct dwc2_dregs_backup *dr_backup; 713 - struct dwc2_hregs_backup *hr_backup; 708 + struct dwc2_gregs_backup gr_backup; 709 + struct dwc2_dregs_backup dr_backup; 710 + struct dwc2_hregs_backup hr_backup; 714 711 715 712 struct dentry *debug_root; 716 713 struct debugfs_regset32 *regset;