diff options
Diffstat (limited to 'drivers')
189 files changed, 1316 insertions, 752 deletions
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index b5730e17b455..656624314f0d 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -315,24 +315,32 @@ void drbd_req_complete(struct drbd_request *req, struct bio_and_error *m) } /* still holds resource->req_lock */ -static int drbd_req_put_completion_ref(struct drbd_request *req, struct bio_and_error *m, int put) +static void drbd_req_put_completion_ref(struct drbd_request *req, struct bio_and_error *m, int put) { struct drbd_device *device = req->device; D_ASSERT(device, m || (req->rq_state & RQ_POSTPONED)); + if (!put) + return; + if (!atomic_sub_and_test(put, &req->completion_ref)) - return 0; + return; drbd_req_complete(req, m); + /* local completion may still come in later, + * we need to keep the req object around. */ + if (req->rq_state & RQ_LOCAL_ABORTED) + return; + if (req->rq_state & RQ_POSTPONED) { /* don't destroy the req object just yet, * but queue it for retry */ drbd_restart_request(req); - return 0; + return; } - return 1; + kref_put(&req->kref, drbd_req_destroy); } static void set_if_null_req_next(struct drbd_peer_device *peer_device, struct drbd_request *req) @@ -519,12 +527,8 @@ static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m, if (req->i.waiting) wake_up(&device->misc_wait); - if (c_put) { - if (drbd_req_put_completion_ref(req, m, c_put)) - kref_put(&req->kref, drbd_req_destroy); - } else { - kref_put(&req->kref, drbd_req_destroy); - } + drbd_req_put_completion_ref(req, m, c_put); + kref_put(&req->kref, drbd_req_destroy); } static void drbd_report_io_error(struct drbd_device *device, struct drbd_request *req) @@ -1366,8 +1370,7 @@ nodata: } out: - if (drbd_req_put_completion_ref(req, &m, 1)) - kref_put(&req->kref, drbd_req_destroy); + drbd_req_put_completion_ref(req, &m, 1); spin_unlock_irq(&resource->req_lock); /* Even though above is a kref_put(), this is safe. diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 8fe61b5dc5a6..1f3dfaa54d87 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -504,11 +504,13 @@ static int xen_blkbk_remove(struct xenbus_device *dev) dev_set_drvdata(&dev->dev, NULL); - if (be->blkif) + if (be->blkif) { xen_blkif_disconnect(be->blkif); - /* Put the reference we set in xen_blkif_alloc(). */ - xen_blkif_put(be->blkif); + /* Put the reference we set in xen_blkif_alloc(). */ + xen_blkif_put(be->blkif); + } + kfree(be->mode); kfree(be); return 0; diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 565e4cf04a02..8249762192d5 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -859,7 +859,11 @@ static int __init lp_setup (char *str) } else if (!strcmp(str, "auto")) { parport_nr[0] = LP_PARPORT_AUTO; } else if (!strcmp(str, "none")) { - parport_nr[parport_ptr++] = LP_PARPORT_NONE; + if (parport_ptr < LP_NO) + parport_nr[parport_ptr++] = LP_PARPORT_NONE; + else + printk(KERN_INFO "lp: too many ports, %s ignored.\n", + str); } else if (!strcmp(str, "reset")) { reset = 1; } diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 7e4a9d1296bb..6e0cbe092220 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -340,6 +340,11 @@ static const struct vm_operations_struct mmap_mem_ops = { static int mmap_mem(struct file *file, struct vm_area_struct *vma) { size_t size = vma->vm_end - vma->vm_start; + phys_addr_t offset = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT; + + /* It's illegal to wrap around the end of the physical address space. */ + if (offset + (phys_addr_t)size < offset) + return -EINVAL; if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size)) return -EINVAL; diff --git a/drivers/dax/super.c b/drivers/dax/super.c index ebf43f531ada..6ed32aac8bbe 100644 --- a/drivers/dax/super.c +++ b/drivers/dax/super.c @@ -44,6 +44,7 @@ void dax_read_unlock(int id) } EXPORT_SYMBOL_GPL(dax_read_unlock); +#ifdef CONFIG_BLOCK int bdev_dax_pgoff(struct block_device *bdev, sector_t sector, size_t size, pgoff_t *pgoff) { @@ -112,6 +113,7 @@ int __bdev_dax_supported(struct super_block *sb, int blocksize) return 0; } EXPORT_SYMBOL_GPL(__bdev_dax_supported); +#endif /** * struct dax_device - anchor object for dax services diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 82dab1692264..3aea55698165 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -782,24 +782,26 @@ static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan) static void debug_display_dimm_sizes_df(struct amd64_pvt *pvt, u8 ctrl) { - u32 *dcsb = ctrl ? pvt->csels[1].csbases : pvt->csels[0].csbases; - int dimm, size0, size1; + int dimm, size0, size1, cs0, cs1; edac_printk(KERN_DEBUG, EDAC_MC, "UMC%d chip selects:\n", ctrl); for (dimm = 0; dimm < 4; dimm++) { size0 = 0; + cs0 = dimm * 2; - if (dcsb[dimm*2] & DCSB_CS_ENABLE) - size0 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, dimm); + if (csrow_enabled(cs0, ctrl, pvt)) + size0 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, cs0); size1 = 0; - if (dcsb[dimm*2 + 1] & DCSB_CS_ENABLE) - size1 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, dimm); + cs1 = dimm * 2 + 1; + + if (csrow_enabled(cs1, ctrl, pvt)) + size1 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, cs1); amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n", - dimm * 2, size0, - dimm * 2 + 1, size1); + cs0, size0, + cs1, size1); } } @@ -2756,26 +2758,22 @@ skip: * encompasses * */ -static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr) +static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr_orig) { - u32 cs_mode, nr_pages; u32 dbam = dct ? pvt->dbam1 : pvt->dbam0; + int csrow_nr = csrow_nr_orig; + u32 cs_mode, nr_pages; + if (!pvt->umc) + csrow_nr >>= 1; - /* - * The math on this doesn't look right on the surface because x/2*4 can - * be simplified to x*2 but this expression makes use of the fact that - * it is integral math where 1/2=0. This intermediate value becomes the - * number of bits to shift the DBAM register to extract the proper CSROW - * field. - */ - cs_mode = DBAM_DIMM(csrow_nr / 2, dbam); + cs_mode = DBAM_DIMM(csrow_nr, dbam); - nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, (csrow_nr / 2)) - << (20 - PAGE_SHIFT); + nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, csrow_nr); + nr_pages <<= 20 - PAGE_SHIFT; edac_dbg(0, "csrow: %d, channel: %d, DBAM idx: %d\n", - csrow_nr, dct, cs_mode); + csrow_nr_orig, dct, cs_mode); edac_dbg(0, "nr_pages/channel: %u\n", nr_pages); return nr_pages; diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c index ed3137c1ceb0..ab3a951a17e6 100644 --- a/drivers/firmware/efi/efi-pstore.c +++ b/drivers/firmware/efi/efi-pstore.c @@ -155,19 +155,14 @@ static int efi_pstore_scan_sysfs_exit(struct efivar_entry *pos, * efi_pstore_sysfs_entry_iter * * @record: pstore record to pass to callback - * @pos: entry to begin iterating from * * You MUST call efivar_enter_iter_begin() before this function, and * efivar_entry_iter_end() afterwards. * - * It is possible to begin iteration from an arbitrary entry within - * the list by passing @pos. @pos is updated on return to point to - * the next entry of the last one passed to efi_pstore_read_func(). - * To begin iterating from the beginning of the list @pos must be %NULL. */ -static int efi_pstore_sysfs_entry_iter(struct pstore_record *record, - struct efivar_entry **pos) +static int efi_pstore_sysfs_entry_iter(struct pstore_record *record) { + struct efivar_entry **pos = (struct efivar_entry **)&record->psi->data; struct efivar_entry *entry, *n; struct list_head *head = &efivar_sysfs_list; int size = 0; @@ -218,7 +213,6 @@ static int efi_pstore_sysfs_entry_iter(struct pstore_record *record, */ static ssize_t efi_pstore_read(struct pstore_record *record) { - struct efivar_entry *entry = (struct efivar_entry *)record->psi->data; ssize_t size; record->buf = kzalloc(EFIVARS_DATA_SIZE_MAX, GFP_KERNEL); @@ -229,7 +223,7 @@ static ssize_t efi_pstore_read(struct pstore_record *record) size = -EINTR; goto out; } - size = efi_pstore_sysfs_entry_iter(record, &entry); + size = efi_pstore_sysfs_entry_iter(record); efivar_entry_iter_end(); out: diff --git a/drivers/firmware/google/vpd.c b/drivers/firmware/google/vpd.c index 3ce813110d5e..1e7860f02f4f 100644 --- a/drivers/firmware/google/vpd.c +++ b/drivers/firmware/google/vpd.c @@ -116,9 +116,13 @@ static int vpd_section_attrib_add(const u8 *key, s32 key_len, return VPD_OK; info = kzalloc(sizeof(*info), GFP_KERNEL); - info->key = kzalloc(key_len + 1, GFP_KERNEL); - if (!info->key) + if (!info) return -ENOMEM; + info->key = kzalloc(key_len + 1, GFP_KERNEL); + if (!info->key) { + ret = -ENOMEM; + goto free_info; + } memcpy(info->key, key, key_len); @@ -135,12 +139,17 @@ static int vpd_section_attrib_add(const u8 *key, s32 key_len, list_add_tail(&info->list, &sec->attribs); ret = sysfs_create_bin_file(sec->kobj, &info->bin_attr); - if (ret) { - kfree(info->key); - return ret; - } + if (ret) + goto free_info_key; return 0; + +free_info_key: + kfree(info->key); +free_info: + kfree(info); + + return ret; } static void vpd_section_attrib_destroy(struct vpd_section *sec) diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index 874ff32db366..00cfed3c3e1a 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -202,7 +202,8 @@ static int ti_sci_debugfs_create(struct platform_device *pdev, info->debug_buffer[info->debug_region_size] = 0; info->d = debugfs_create_file(strncat(debug_name, dev_name(dev), - sizeof(debug_name)), + sizeof(debug_name) - + sizeof("ti_sci_debug@")), 0444, NULL, info, &ti_sci_debug_fops); if (IS_ERR(info->d)) return PTR_ERR(info->d); diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index 798a3cc480a2..1a3359c0f6cd 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c @@ -10,6 +10,7 @@ */ #include <drm/drmP.h> +#include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> @@ -226,16 +227,33 @@ static const struct drm_crtc_helper_funcs hdlcd_crtc_helper_funcs = { static int hdlcd_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) { - u32 src_w, src_h; + struct drm_rect clip = { 0 }; + struct drm_crtc_state *crtc_state; + u32 src_h = state->src_h >> 16; - src_w = state->src_w >> 16; - src_h = state->src_h >> 16; + /* only the HDLCD_REG_FB_LINE_COUNT register has a limit */ + if (src_h >= HDLCD_MAX_YRES) { + DRM_DEBUG_KMS("Invalid source width: %d\n", src_h); + return -EINVAL; + } + + if (!state->fb || !state->crtc) + return 0; - /* we can't do any scaling of the plane source */ - if ((src_w != state->crtc_w) || (src_h != state->crtc_h)) + crtc_state = drm_atomic_get_existing_crtc_state(state->state, + state->crtc); + if (!crtc_state) { + DRM_DEBUG_KMS("Invalid crtc state\n"); return -EINVAL; + } - return 0; + clip.x2 = crtc_state->adjusted_mode.hdisplay; + clip.y2 = crtc_state->adjusted_mode.vdisplay; + + return drm_plane_helper_check_state(state, &clip, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + false, true); } static void hdlcd_plane_atomic_update(struct drm_plane *plane, @@ -244,21 +262,20 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane, struct drm_framebuffer *fb = plane->state->fb; struct hdlcd_drm_private *hdlcd; struct drm_gem_cma_object *gem; - u32 src_w, src_h, dest_w, dest_h; + u32 src_x, src_y, dest_h; dma_addr_t scanout_start; if (!fb) return; - src_w = plane->state->src_w >> 16; - src_h = plane->state->src_h >> 16; - dest_w = plane->state->crtc_w; - dest_h = plane->state->crtc_h; + src_x = plane->state->src.x1 >> 16; + src_y = plane->state->src.y1 >> 16; + dest_h = drm_rect_height(&plane->state->dst); gem = drm_fb_cma_get_gem_obj(fb, 0); + scanout_start = gem->paddr + fb->offsets[0] + - plane->state->crtc_y * fb->pitches[0] + - plane->state->crtc_x * - fb->format->cpp[0]; + src_y * fb->pitches[0] + + src_x * fb->format->cpp[0]; hdlcd = plane->dev->dev_private; hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, fb->pitches[0]); @@ -305,7 +322,6 @@ static struct drm_plane *hdlcd_plane_init(struct drm_device *drm) formats, ARRAY_SIZE(formats), DRM_PLANE_TYPE_PRIMARY, NULL); if (ret) { - devm_kfree(drm->dev, plane); return ERR_PTR(ret); } @@ -329,7 +345,6 @@ int hdlcd_setup_crtc(struct drm_device *drm) &hdlcd_crtc_funcs, NULL); if (ret) { hdlcd_plane_destroy(primary); - devm_kfree(drm->dev, primary); return ret; } diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c index 65a3bd7a0c00..423dda2785d4 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c @@ -152,8 +152,7 @@ static const struct drm_connector_funcs atmel_hlcdc_panel_connector_funcs = { .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; -static int atmel_hlcdc_attach_endpoint(struct drm_device *dev, - const struct device_node *np) +static int atmel_hlcdc_attach_endpoint(struct drm_device *dev, int endpoint) { struct atmel_hlcdc_dc *dc = dev->dev_private; struct atmel_hlcdc_rgb_output *output; @@ -161,6 +160,11 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev, struct drm_bridge *bridge; int ret; + ret = drm_of_find_panel_or_bridge(dev->dev->of_node, 0, endpoint, + &panel, &bridge); + if (ret) + return ret; + output = devm_kzalloc(dev->dev, sizeof(*output), GFP_KERNEL); if (!output) return -EINVAL; @@ -177,10 +181,6 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev, output->encoder.possible_crtcs = 0x1; - ret = drm_of_find_panel_or_bridge(np, 0, 0, &panel, &bridge); - if (ret) - return ret; - if (panel) { output->connector.dpms = DRM_MODE_DPMS_OFF; output->connector.polled = DRM_CONNECTOR_POLL_CONNECT; @@ -220,22 +220,14 @@ err_encoder_cleanup: int atmel_hlcdc_create_outputs(struct drm_device *dev) { - struct device_node *remote; - int ret = -ENODEV; - int endpoint = 0; - - while (true) { - /* Loop thru possible multiple connections to the output */ - remote = of_graph_get_remote_node(dev->dev->of_node, 0, - endpoint++); - if (!remote) - break; - - ret = atmel_hlcdc_attach_endpoint(dev, remote); - of_node_put(remote); - if (ret) - return ret; - } + int endpoint, ret = 0; + + for (endpoint = 0; !ret; endpoint++) + ret = atmel_hlcdc_attach_endpoint(dev, endpoint); + + /* At least one device was successfully attached.*/ + if (ret == -ENODEV && endpoint) + return 0; return ret; } diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c index e1909429837e..de80ee1b71df 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c @@ -44,6 +44,7 @@ static struct etnaviv_gem_submit *submit_create(struct drm_device *dev, /* initially, until copy_from_user() and bo lookup succeeds: */ submit->nr_bos = 0; + submit->fence = NULL; ww_acquire_init(&submit->ticket, &reservation_ww_class); } @@ -294,7 +295,8 @@ static void submit_cleanup(struct etnaviv_gem_submit *submit) } ww_acquire_fini(&submit->ticket); - dma_fence_put(submit->fence); + if (submit->fence) + dma_fence_put(submit->fence); kfree(submit); } diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 0ad1a508e2af..c995e540ff96 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -1244,7 +1244,7 @@ static int dma_ctrl_write(struct intel_vgpu *vgpu, unsigned int offset, mode = vgpu_vreg(vgpu, offset); if (GFX_MODE_BIT_SET_IN_MASK(mode, START_DMA)) { - WARN_ONCE(1, "VM(%d): iGVT-g doesn't supporte GuC\n", + WARN_ONCE(1, "VM(%d): iGVT-g doesn't support GuC\n", vgpu->id); return 0; } diff --git a/drivers/gpu/drm/i915/gvt/render.c b/drivers/gpu/drm/i915/gvt/render.c index c6e7972ac21d..a5e11d89df2f 100644 --- a/drivers/gpu/drm/i915/gvt/render.c +++ b/drivers/gpu/drm/i915/gvt/render.c @@ -340,6 +340,9 @@ void intel_gvt_restore_render_mmio(struct intel_vgpu *vgpu, int ring_id) } else v = mmio->value; + if (mmio->in_context) + continue; + I915_WRITE(mmio->reg, v); POSTING_READ(mmio->reg); diff --git a/drivers/gpu/drm/i915/gvt/sched_policy.c b/drivers/gpu/drm/i915/gvt/sched_policy.c index 79ba4b3440aa..f25ff133865f 100644 --- a/drivers/gpu/drm/i915/gvt/sched_policy.c +++ b/drivers/gpu/drm/i915/gvt/sched_policy.c @@ -129,9 +129,13 @@ static void try_to_schedule_next_vgpu(struct intel_gvt *gvt) struct vgpu_sched_data *vgpu_data; ktime_t cur_time; - /* no target to schedule */ - if (!scheduler->next_vgpu) + /* no need to schedule if next_vgpu is the same with current_vgpu, + * let scheduler chose next_vgpu again by setting it to NULL. + */ + if (scheduler->next_vgpu == scheduler->current_vgpu) { + scheduler->next_vgpu = NULL; return; + } /* * after the flag is set, workload dispatch thread will diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 2aa6b97fd22f..a0563e18d753 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -195,9 +195,12 @@ static int ppgtt_bind_vma(struct i915_vma *vma, u32 pte_flags; int ret; - ret = vma->vm->allocate_va_range(vma->vm, vma->node.start, vma->size); - if (ret) - return ret; + if (!(vma->flags & I915_VMA_LOCAL_BIND)) { + ret = vma->vm->allocate_va_range(vma->vm, vma->node.start, + vma->size); + if (ret) + return ret; + } vma->pages = vma->obj->mm.pages; @@ -2306,7 +2309,8 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma, if (flags & I915_VMA_LOCAL_BIND) { struct i915_hw_ppgtt *appgtt = i915->mm.aliasing_ppgtt; - if (appgtt->base.allocate_va_range) { + if (!(vma->flags & I915_VMA_LOCAL_BIND) && + appgtt->base.allocate_va_range) { ret = appgtt->base.allocate_va_range(&appgtt->base, vma->node.start, vma->node.size); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 11b12f412492..5a7c63e64381 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3051,10 +3051,14 @@ enum skl_disp_power_wells { #define CLKCFG_FSB_667 (3 << 0) /* hrawclk 166 */ #define CLKCFG_FSB_800 (2 << 0) /* hrawclk 200 */ #define CLKCFG_FSB_1067 (6 << 0) /* hrawclk 266 */ +#define CLKCFG_FSB_1067_ALT (0 << 0) /* hrawclk 266 */ #define CLKCFG_FSB_1333 (7 << 0) /* hrawclk 333 */ -/* Note, below two are guess */ -#define CLKCFG_FSB_1600 (4 << 0) /* hrawclk 400 */ -#define CLKCFG_FSB_1600_ALT (0 << 0) /* hrawclk 400 */ +/* + * Note that on at least on ELK the below value is reported for both + * 333 and 400 MHz BIOS FSB setting, but given that the gmch datasheet + * lists only 200/266/333 MHz FSB as supported let's decode it as 333 MHz. + */ +#define CLKCFG_FSB_1333_ALT (4 << 0) /* hrawclk 333 */ #define CLKCFG_FSB_MASK (7 << 0) #define CLKCFG_MEM_533 (1 << 4) #define CLKCFG_MEM_667 (2 << 4) diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c index dd3ad52b7dfe..f29a226e24d8 100644 --- a/drivers/gpu/drm/i915/intel_cdclk.c +++ b/drivers/gpu/drm/i915/intel_cdclk.c @@ -1798,13 +1798,11 @@ static int g4x_hrawclk(struct drm_i915_private *dev_priv) case CLKCFG_FSB_800: return 200000; case CLKCFG_FSB_1067: + case CLKCFG_FSB_1067_ALT: return 266667; case CLKCFG_FSB_1333: + case CLKCFG_FSB_1333_ALT: return 333333; - /* these two are just a guess; one of them might be right */ - case CLKCFG_FSB_1600: - case CLKCFG_FSB_1600_ALT: - return 400000; default: return 133333; } diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 3ffe8b1f1d48..fc0ef492252a 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -410,11 +410,10 @@ static void glk_dsi_device_ready(struct intel_encoder *encoder) val |= (ULPS_STATE_ENTER | DEVICE_READY); I915_WRITE(MIPI_DEVICE_READY(port), val); - /* Wait for ULPS Not active */ + /* Wait for ULPS active */ if (intel_wait_for_register(dev_priv, - MIPI_CTRL(port), GLK_ULPS_NOT_ACTIVE, - GLK_ULPS_NOT_ACTIVE, 20)) - DRM_ERROR("ULPS is still active\n"); + MIPI_CTRL(port), GLK_ULPS_NOT_ACTIVE, 0, 20)) + DRM_ERROR("ULPS not active\n"); /* Exit ULPS */ val = I915_READ(MIPI_DEVICE_READY(port)); diff --git a/drivers/gpu/drm/i915/intel_lpe_audio.c b/drivers/gpu/drm/i915/intel_lpe_audio.c index 25d8e76489e4..668f00480d97 100644 --- a/drivers/gpu/drm/i915/intel_lpe_audio.c +++ b/drivers/gpu/drm/i915/intel_lpe_audio.c @@ -63,6 +63,7 @@ #include <linux/acpi.h> #include <linux/device.h> #include <linux/pci.h> +#include <linux/pm_runtime.h> #include "i915_drv.h" #include <linux/delay.h> @@ -121,6 +122,10 @@ lpe_audio_platdev_create(struct drm_i915_private *dev_priv) kfree(rsc); + pm_runtime_forbid(&platdev->dev); + pm_runtime_set_active(&platdev->dev); + pm_runtime_enable(&platdev->dev); + return platdev; err: diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 21b10f9840c9..549763f5e17d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -360,6 +360,8 @@ nouveau_display_hpd_work(struct work_struct *work) pm_runtime_get_sync(drm->dev->dev); drm_helper_hpd_irq_event(drm->dev); + /* enable polling for external displays */ + drm_kms_helper_poll_enable(drm->dev); pm_runtime_mark_last_busy(drm->dev->dev); pm_runtime_put_sync(drm->dev->dev); @@ -413,10 +415,6 @@ nouveau_display_init(struct drm_device *dev) if (ret) return ret; - /* enable polling for external displays */ - if (!dev->mode_config.poll_enabled) - drm_kms_helper_poll_enable(dev); - /* enable hotplug interrupts */ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct nouveau_connector *conn = nouveau_connector(connector); diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 2b6ac24ce690..36268e1802b5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -502,6 +502,9 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) pm_runtime_allow(dev->dev); pm_runtime_mark_last_busy(dev->dev); pm_runtime_put(dev->dev); + } else { + /* enable polling for external displays */ + drm_kms_helper_poll_enable(dev); } return 0; @@ -774,9 +777,6 @@ nouveau_pmops_runtime_resume(struct device *dev) ret = nouveau_do_resume(drm_dev, true); - if (!drm_dev->mode_config.poll_enabled) - drm_kms_helper_poll_enable(drm_dev); - /* do magic */ nvif_mask(&device->object, 0x088488, (1 << 25), (1 << 25)); vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index 3a24788c3185..a7e55c422501 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -148,7 +148,7 @@ gk104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl) case NVKM_MEM_TARGET_NCOH: target = 3; break; default: WARN_ON(1); - return; + goto unlock; } nvkm_wr32(device, 0x002270, (nvkm_memory_addr(mem) >> 12) | @@ -160,6 +160,7 @@ gk104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl) & 0x00100000), msecs_to_jiffies(2000)) == 0) nvkm_error(subdev, "runlist %d update timeout\n", runl); +unlock: mutex_unlock(&subdev->mutex); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_gr.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_gr.c index d1cf02d22db1..1b0c793c0192 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_gr.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_gr.c @@ -116,6 +116,7 @@ ls_ucode_img_load_gr(const struct nvkm_subdev *subdev, struct ls_ucode_img *img, ret = nvkm_firmware_get(subdev->device, f, &sig); if (ret) goto free_data; + img->sig = kmemdup(sig->data, sig->size, GFP_KERNEL); if (!img->sig) { ret = -ENOMEM; @@ -126,8 +127,9 @@ ls_ucode_img_load_gr(const struct nvkm_subdev *subdev, struct ls_ucode_img *img, img->ucode_data = ls_ucode_img_build(bl, code, data, &img->ucode_desc); if (IS_ERR(img->ucode_data)) { + kfree(img->sig); ret = PTR_ERR(img->ucode_data); - goto free_data; + goto free_sig; } img->ucode_size = img->ucode_desc.image_size; diff --git a/drivers/gpu/host1x/Kconfig b/drivers/gpu/host1x/Kconfig index b2fd029d67b3..91916326957f 100644 --- a/drivers/gpu/host1x/Kconfig +++ b/drivers/gpu/host1x/Kconfig @@ -1,6 +1,7 @@ config TEGRA_HOST1X tristate "NVIDIA Tegra host1x driver" depends on ARCH_TEGRA || (ARM && COMPILE_TEST) + select IOMMU_IOVA if IOMMU_SUPPORT help Driver for the NVIDIA Tegra host1x hardware. diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 3ac4c03ba77b..c13a4fd86b3c 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -605,6 +605,13 @@ static int coretemp_cpu_online(unsigned int cpu) struct platform_data *pdata; /* + * Don't execute this on resume as the offline callback did + * not get executed on suspend. + */ + if (cpuhp_tasks_frozen) + return 0; + + /* * CPUID.06H.EAX[0] indicates whether the CPU has thermal * sensors. We check this bit only, all the early CPUs * without thermal sensors will be filtered out. @@ -654,6 +661,13 @@ static int coretemp_cpu_offline(unsigned int cpu) struct temp_data *tdata; int indx, target; + /* + * Don't execute this on suspend as the device remove locks + * up the machine. + */ + if (cpuhp_tasks_frozen) + return 0; + /* If the physical CPU device does not exist, just return */ if (!pdev) return 0; diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index f2acd4b6bf01..6283b99d2b17 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -96,6 +96,7 @@ static int dw_i2c_acpi_configure(struct platform_device *pdev) struct dw_i2c_dev *dev = platform_get_drvdata(pdev); acpi_handle handle = ACPI_HANDLE(&pdev->dev); const struct acpi_device_id *id; + u32 ss_ht, fp_ht, hs_ht, fs_ht; struct acpi_device *adev; const char *uid; @@ -107,23 +108,24 @@ static int dw_i2c_acpi_configure(struct platform_device *pdev) * Try to get SDA hold time and *CNT values from an ACPI method for * selected speed modes. */ + dw_i2c_acpi_params(pdev, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt, &ss_ht); + dw_i2c_acpi_params(pdev, "FPCN", &dev->fp_hcnt, &dev->fp_lcnt, &fp_ht); + dw_i2c_acpi_params(pdev, "HSCN", &dev->hs_hcnt, &dev->hs_lcnt, &hs_ht); + dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt, &fs_ht); + switch (dev->clk_freq) { case 100000: - dw_i2c_acpi_params(pdev, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt, - &dev->sda_hold_time); + dev->sda_hold_time = ss_ht; break; case 1000000: - dw_i2c_acpi_params(pdev, "FPCN", &dev->fp_hcnt, &dev->fp_lcnt, - &dev->sda_hold_time); + dev->sda_hold_time = fp_ht; break; case 3400000: - dw_i2c_acpi_params(pdev, "HSCN", &dev->hs_hcnt, &dev->hs_lcnt, - &dev->sda_hold_time); + dev->sda_hold_time = hs_ht; break; case 400000: default: - dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt, - &dev->sda_hold_time); + dev->sda_hold_time = fs_ht; break; } diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index cf737ec8563b..5c4db65c5019 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -819,7 +819,6 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, rc = -EINVAL; goto out; } - drv_data->irq = irq_of_parse_and_map(np, 0); drv_data->rstc = devm_reset_control_get_optional(dev, NULL); if (IS_ERR(drv_data->rstc)) { @@ -902,10 +901,11 @@ mv64xxx_i2c_probe(struct platform_device *pd) if (!IS_ERR(drv_data->clk)) clk_prepare_enable(drv_data->clk); + drv_data->irq = platform_get_irq(pd, 0); + if (pdata) { drv_data->freq_m = pdata->freq_m; drv_data->freq_n = pdata->freq_n; - drv_data->irq = platform_get_irq(pd, 0); drv_data->adapter.timeout = msecs_to_jiffies(pdata->timeout); drv_data->offload_enabled = false; memcpy(&drv_data->reg_offsets, &mv64xxx_i2c_regs_mv64xxx, sizeof(drv_data->reg_offsets)); @@ -915,7 +915,7 @@ mv64xxx_i2c_probe(struct platform_device *pd) goto exit_clk; } if (drv_data->irq < 0) { - rc = -ENXIO; + rc = drv_data->irq; goto exit_reset; } diff --git a/drivers/i2c/busses/i2c-xgene-slimpro.c b/drivers/i2c/busses/i2c-xgene-slimpro.c index dbe7e44c9321..6ba6c83ca8f1 100644 --- a/drivers/i2c/busses/i2c-xgene-slimpro.c +++ b/drivers/i2c/busses/i2c-xgene-slimpro.c @@ -416,6 +416,7 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev) adapter->class = I2C_CLASS_HWMON; adapter->dev.parent = &pdev->dev; adapter->dev.of_node = pdev->dev.of_node; + ACPI_COMPANION_SET(&adapter->dev, ACPI_COMPANION(&pdev->dev)); i2c_set_adapdata(adapter, ctx); rc = i2c_add_adapter(adapter); if (rc) { diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c index 26f7237558ba..9669ca4937b8 100644 --- a/drivers/i2c/i2c-mux.c +++ b/drivers/i2c/i2c-mux.c @@ -395,18 +395,20 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc, if (force_nr) { priv->adap.nr = force_nr; ret = i2c_add_numbered_adapter(&priv->adap); - dev_err(&parent->dev, - "failed to add mux-adapter %u as bus %u (error=%d)\n", - chan_id, force_nr, ret); + if (ret < 0) { + dev_err(&parent->dev, + "failed to add mux-adapter %u as bus %u (error=%d)\n", + chan_id, force_nr, ret); + goto err_free_priv; + } } else { ret = i2c_add_adapter(&priv->adap); - dev_err(&parent->dev, - "failed to add mux-adapter %u (error=%d)\n", - chan_id, ret); - } - if (ret < 0) { - kfree(priv); - return ret; + if (ret < 0) { + dev_err(&parent->dev, + "failed to add mux-adapter %u (error=%d)\n", + chan_id, ret); + goto err_free_priv; + } } WARN(sysfs_create_link(&priv->adap.dev.kobj, &muxc->dev->kobj, @@ -422,6 +424,10 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc, muxc->adapter[muxc->num_adapters++] = &priv->adap; return 0; + +err_free_priv: + kfree(priv); + return ret; } EXPORT_SYMBOL_GPL(i2c_mux_add_adapter); diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c index 406d5059072c..d97031804de8 100644 --- a/drivers/i2c/muxes/i2c-mux-reg.c +++ b/drivers/i2c/muxes/i2c-mux-reg.c @@ -196,20 +196,25 @@ static int i2c_mux_reg_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); mux->data.reg_size = resource_size(res); mux->data.reg = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(mux->data.reg)) - return PTR_ERR(mux->data.reg); + if (IS_ERR(mux->data.reg)) { + ret = PTR_ERR(mux->data.reg); + goto err_put_parent; + } } if (mux->data.reg_size != 4 && mux->data.reg_size != 2 && mux->data.reg_size != 1) { dev_err(&pdev->dev, "Invalid register size\n"); - return -EINVAL; + ret = -EINVAL; + goto err_put_parent; } muxc = i2c_mux_alloc(parent, &pdev->dev, mux->data.n_values, 0, 0, i2c_mux_reg_select, NULL); - if (!muxc) - return -ENOMEM; + if (!muxc) { + ret = -ENOMEM; + goto err_put_parent; + } muxc->priv = mux; platform_set_drvdata(pdev, muxc); @@ -223,7 +228,7 @@ static int i2c_mux_reg_probe(struct platform_device *pdev) ret = i2c_mux_add_adapter(muxc, nr, mux->data.values[i], class); if (ret) - goto add_adapter_failed; + goto err_del_mux_adapters; } dev_dbg(&pdev->dev, "%d port mux on %s adapter\n", @@ -231,8 +236,10 @@ static int i2c_mux_reg_probe(struct platform_device *pdev) return 0; -add_adapter_failed: +err_del_mux_adapters: i2c_mux_del_adapters(muxc); +err_put_parent: + i2c_put_adapter(parent); return ret; } diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index 8348f366ddd1..62618e77bedc 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -396,13 +396,13 @@ static void iommu_dma_free_iova(struct iommu_dma_cookie *cookie, dma_addr_t iova, size_t size) { struct iova_domain *iovad = &cookie->iovad; - unsigned long shift = iova_shift(iovad); /* The MSI case is only ever cleaning up its most recent allocation */ if (cookie->type == IOMMU_DMA_MSI_COOKIE) cookie->msi_iova -= size; else - free_iova_fast(iovad, iova >> shift, size >> shift); + free_iova_fast(iovad, iova_pfn(iovad, iova), + size >> iova_shift(iovad)); } static void __iommu_dma_unmap(struct iommu_domain *domain, dma_addr_t dma_addr, @@ -617,11 +617,14 @@ static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys, { struct iommu_domain *domain = iommu_get_domain_for_dev(dev); struct iommu_dma_cookie *cookie = domain->iova_cookie; - struct iova_domain *iovad = &cookie->iovad; - size_t iova_off = iova_offset(iovad, phys); + size_t iova_off = 0; dma_addr_t iova; - size = iova_align(iovad, size + iova_off); + if (cookie->type == IOMMU_DMA_IOVA_COOKIE) { + iova_off = iova_offset(&cookie->iovad, phys); + size = iova_align(&cookie->iovad, size + iova_off); + } + iova = iommu_dma_alloc_iova(domain, size, dma_get_mask(dev), dev); if (!iova) return DMA_ERROR_CODE; diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 90ab0115d78e..fc2765ccdb57 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -2055,11 +2055,14 @@ static int domain_context_mapping_one(struct dmar_domain *domain, if (context_copied(context)) { u16 did_old = context_domain_id(context); - if (did_old >= 0 && did_old < cap_ndoms(iommu->cap)) + if (did_old >= 0 && did_old < cap_ndoms(iommu->cap)) { iommu->flush.flush_context(iommu, did_old, (((u16)bus) << 8) | devfn, DMA_CCMD_MASK_NOBIT, DMA_CCMD_DEVICE_INVL); + iommu->flush.flush_iotlb(iommu, did_old, 0, 0, + DMA_TLB_DSI_FLUSH); + } } pgd = domain->pgd; diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c index a27ef570c328..bc1efbfb9ddf 100644 --- a/drivers/iommu/mtk_iommu_v1.c +++ b/drivers/iommu/mtk_iommu_v1.c @@ -18,6 +18,7 @@ #include <linux/clk.h> #include <linux/component.h> #include <linux/device.h> +#include <linux/dma-mapping.h> #include <linux/dma-iommu.h> #include <linux/err.h> #include <linux/interrupt.h> diff --git a/drivers/irqchip/irq-mbigen.c b/drivers/irqchip/irq-mbigen.c index d2306c821ebb..31d6b5a582d2 100644 --- a/drivers/irqchip/irq-mbigen.c +++ b/drivers/irqchip/irq-mbigen.c @@ -106,10 +106,7 @@ static inline void get_mbigen_type_reg(irq_hw_number_t hwirq, static inline void get_mbigen_clear_reg(irq_hw_number_t hwirq, u32 *mask, u32 *addr) { - unsigned int ofst; - - hwirq -= RESERVED_IRQ_PER_MBIGEN_CHIP; - ofst = hwirq / 32 * 4; + unsigned int ofst = (hwirq / 32) * 4; *mask = 1 << (hwirq % 32); *addr = ofst + REG_MBIGEN_CLEAR_OFFSET; @@ -337,9 +334,15 @@ static int mbigen_device_probe(struct platform_device *pdev) mgn_chip->pdev = pdev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mgn_chip->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(mgn_chip->base)) - return PTR_ERR(mgn_chip->base); + if (!res) + return -EINVAL; + + mgn_chip->base = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!mgn_chip->base) { + dev_err(&pdev->dev, "failed to ioremap %pR\n", res); + return -ENOMEM; + } if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) err = mbigen_of_create_domain(pdev, mgn_chip); diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index 5db11a405129..cd8139593ccd 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c @@ -218,7 +218,7 @@ static DEFINE_SPINLOCK(param_spinlock); * Buffers are freed after this timeout */ static unsigned dm_bufio_max_age = DM_BUFIO_DEFAULT_AGE_SECS; -static unsigned dm_bufio_retain_bytes = DM_BUFIO_DEFAULT_RETAIN_BYTES; +static unsigned long dm_bufio_retain_bytes = DM_BUFIO_DEFAULT_RETAIN_BYTES; static unsigned long dm_bufio_peak_allocated; static unsigned long dm_bufio_allocated_kmem_cache; @@ -1558,10 +1558,10 @@ static bool __try_evict_buffer(struct dm_buffer *b, gfp_t gfp) return true; } -static unsigned get_retain_buffers(struct dm_bufio_client *c) +static unsigned long get_retain_buffers(struct dm_bufio_client *c) { - unsigned retain_bytes = ACCESS_ONCE(dm_bufio_retain_bytes); - return retain_bytes / c->block_size; + unsigned long retain_bytes = ACCESS_ONCE(dm_bufio_retain_bytes); + return retain_bytes >> (c->sectors_per_block_bits + SECTOR_SHIFT); } static unsigned long __scan(struct dm_bufio_client *c, unsigned long nr_to_scan, @@ -1571,7 +1571,7 @@ static unsigned long __scan(struct dm_bufio_client *c, unsigned long nr_to_scan, struct dm_buffer *b, *tmp; unsigned long freed = 0; unsigned long count = nr_to_scan; - unsigned retain_target = get_retain_buffers(c); + unsigned long retain_target = get_retain_buffers(c); for (l = 0; l < LIST_SIZE; l++) { list_for_each_entry_safe_reverse(b, tmp, &c->lru[l], lru_list) { @@ -1794,8 +1794,8 @@ static bool older_than(struct dm_buffer *b, unsigned long age_hz) static void __evict_old_buffers(struct dm_bufio_client *c, unsigned long age_hz) { struct dm_buffer *b, *tmp; - unsigned retain_target = get_retain_buffers(c); - unsigned count; + unsigned long retain_target = get_retain_buffers(c); + unsigned long count; LIST_HEAD(write_list); dm_bufio_lock(c); @@ -1955,7 +1955,7 @@ MODULE_PARM_DESC(max_cache_size_bytes, "Size of metadata cache"); module_param_named(max_age_seconds, dm_bufio_max_age, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(max_age_seconds, "Max age of a buffer in seconds"); -module_param_named(retain_bytes, dm_bufio_retain_bytes, uint, S_IRUGO | S_IWUSR); +module_param_named(retain_bytes, dm_bufio_retain_bytes, ulong, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(retain_bytes, "Try to keep at least this many bytes cached in memory"); module_param_named(peak_allocated_bytes, dm_bufio_peak_allocated, ulong, S_IRUGO | S_IWUSR); diff --git a/drivers/md/dm-cache-background-tracker.c b/drivers/md/dm-cache-background-tracker.c index 9b1afdfb13f0..707233891291 100644 --- a/drivers/md/dm-cache-background-tracker.c +++ b/drivers/md/dm-cache-background-tracker.c @@ -33,6 +33,11 @@ struct background_tracker *btracker_create(unsigned max_work) { struct background_tracker *b = kmalloc(sizeof(*b), GFP_KERNEL); + if (!b) { + DMERR("couldn't create background_tracker"); + return NULL; + } + b->max_work = max_work; atomic_set(&b->pending_promotes, 0); atomic_set(&b->pending_writebacks, 0); diff --git a/drivers/md/dm-cache-policy-smq.c b/drivers/md/dm-cache-policy-smq.c index 72479bd61e11..e5eb9c9b4bc8 100644 --- a/drivers/md/dm-cache-policy-smq.c +++ b/drivers/md/dm-cache-policy-smq.c @@ -1120,8 +1120,6 @@ static bool clean_target_met(struct smq_policy *mq, bool idle) * Cache entries may not be populated. So we cannot rely on the * size of the clean queue. */ - unsigned nr_clean; - if (idle) { /* * We'd like to clean everything. @@ -1129,18 +1127,16 @@ static bool clean_target_met(struct smq_policy *mq, bool idle) return q_size(&mq->dirty) == 0u; } - nr_clean = from_cblock(mq->cache_size) - q_size(&mq->dirty); - return (nr_clean + btracker_nr_writebacks_queued(mq->bg_work)) >= - percent_to_target(mq, CLEAN_TARGET); + /* + * If we're busy we don't worry about cleaning at all. + */ + return true; } -static bool free_target_met(struct smq_policy *mq, bool idle) +static bool free_target_met(struct smq_policy *mq) { unsigned nr_free; - if (!idle) - return true; - nr_free = from_cblock(mq->cache_size) - mq->cache_alloc.nr_allocated; return (nr_free + btracker_nr_demotions_queued(mq->bg_work)) >= percent_to_target(mq, FREE_TARGET); @@ -1190,9 +1186,9 @@ static void queue_demotion(struct smq_policy *mq) if (unlikely(WARN_ON_ONCE(!mq->migrations_allowed))) return; - e = q_peek(&mq->clean, mq->clean.nr_levels, true); + e = q_peek(&mq->clean, mq->clean.nr_levels / 2, true); if (!e) { - if (!clean_target_met(mq, false)) + if (!clean_target_met(mq, true)) queue_writeback(mq); return; } @@ -1220,7 +1216,7 @@ static void queue_promotion(struct smq_policy *mq, dm_oblock_t oblock, * We always claim to be 'idle' to ensure some demotions happen * with continuous loads. */ - if (!free_target_met(mq, true)) + if (!free_target_met(mq)) queue_demotion(mq); return; } @@ -1421,14 +1417,10 @@ static int smq_get_background_work(struct dm_cache_policy *p, bool idle, spin_lock_irqsave(&mq->lock, flags); r = btracker_issue(mq->bg_work, result); if (r == -ENODATA) { - /* find some writeback work to do */ - if (mq->migrations_allowed && !free_target_met(mq, idle)) - queue_demotion(mq); - - else if (!clean_target_met(mq, idle)) + if (!clean_target_met(mq, idle)) { queue_writeback(mq); - - r = btracker_issue(mq->bg_work, result); + r = btracker_issue(mq->bg_work, result); + } } spin_unlock_irqrestore(&mq->lock, flags); @@ -1452,6 +1444,7 @@ static void __complete_background_work(struct smq_policy *mq, clear_pending(mq, e); if (success) { e->oblock = work->oblock; + e->level = NR_CACHE_LEVELS - 1; push(mq, e); // h, q, a } else { diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index 1db375f50a13..d682a0511381 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -94,6 +94,9 @@ static void iot_io_begin(struct io_tracker *iot, sector_t len) static void __iot_io_end(struct io_tracker *iot, sector_t len) { + if (!len) + return; + iot->in_flight -= len; if (!iot->in_flight) iot->idle_time = jiffies; @@ -474,7 +477,7 @@ struct cache { spinlock_t invalidation_lock; struct list_head invalidation_requests; - struct io_tracker origin_tracker; + struct io_tracker tracker; struct work_struct commit_ws; struct batcher committer; @@ -901,8 +904,7 @@ static dm_oblock_t get_bio_block(struct cache *cache, struct bio *bio) static bool accountable_bio(struct cache *cache, struct bio *bio) { - return ((bio->bi_bdev == cache->origin_dev->bdev) && - bio_op(bio) != REQ_OP_DISCARD); + return bio_op(bio) != REQ_OP_DISCARD; } static void accounted_begin(struct cache *cache, struct bio *bio) @@ -912,7 +914,7 @@ static void accounted_begin(struct cache *cache, struct bio *bio) if (accountable_bio(cache, bio)) { pb->len = bio_sectors(bio); - iot_io_begin(&cache->origin_tracker, pb->len); + iot_io_begin(&cache->tracker, pb->len); } } @@ -921,7 +923,7 @@ static void accounted_complete(struct cache *cache, struct bio *bio) size_t pb_data_size = get_per_bio_data_size(cache); struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size); - iot_io_end(&cache->origin_tracker, pb->len); + iot_io_end(&cache->tracker, pb->len); } static void accounted_request(struct cache *cache, struct bio *bio) @@ -1716,20 +1718,19 @@ static int invalidate_start(struct cache *cache, dm_cblock_t cblock, enum busy { IDLE, - MODERATE, BUSY }; static enum busy spare_migration_bandwidth(struct cache *cache) { - bool idle = iot_idle_for(&cache->origin_tracker, HZ); + bool idle = iot_idle_for(&cache->tracker, HZ); sector_t current_volume = (atomic_read(&cache->nr_io_migrations) + 1) * cache->sectors_per_block; - if (current_volume <= cache->migration_threshold) - return idle ? IDLE : MODERATE; + if (idle && current_volume <= cache->migration_threshold) + return IDLE; else - return idle ? MODERATE : BUSY; + return BUSY; } static void inc_hit_counter(struct cache *cache, struct bio *bio) @@ -2045,8 +2046,6 @@ static void check_migrations(struct work_struct *ws) for (;;) { b = spare_migration_bandwidth(cache); - if (b == BUSY) - break; r = policy_get_background_work(cache->policy, b == IDLE, &op); if (r == -ENODATA) @@ -2717,7 +2716,7 @@ static int cache_create(struct cache_args *ca, struct cache **result) batcher_init(&cache->committer, commit_op, cache, issue_op, cache, cache->wq); - iot_init(&cache->origin_tracker); + iot_init(&cache->tracker); init_rwsem(&cache->background_work_lock); prevent_background_work(cache); @@ -2941,7 +2940,7 @@ static void cache_postsuspend(struct dm_target *ti) cancel_delayed_work(&cache->waker); flush_workqueue(cache->wq); - WARN_ON(cache->origin_tracker.in_flight); + WARN_ON(cache->tracker.in_flight); /* * If it's a flush suspend there won't be any deferred bios, so this diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 926a6bcb32c8..3df056b73b66 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -447,7 +447,7 @@ failed: * it has been invoked. */ #define dm_report_EIO(m) \ -({ \ +do { \ struct mapped_device *md = dm_table_get_md((m)->ti->table); \ \ pr_debug("%s: returning EIO; QIFNP = %d; SQIFNP = %d; DNFS = %d\n", \ @@ -455,8 +455,7 @@ failed: test_bit(MPATHF_QUEUE_IF_NO_PATH, &(m)->flags), \ test_bit(MPATHF_SAVED_QUEUE_IF_NO_PATH, &(m)->flags), \ dm_noflush_suspending((m)->ti)); \ - -EIO; \ -}) +} while (0) /* * Map cloned requests (request-based multipath) @@ -481,7 +480,8 @@ static int multipath_clone_and_map(struct dm_target *ti, struct request *rq, if (!pgpath) { if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) return DM_MAPIO_DELAY_REQUEUE; - return dm_report_EIO(m); /* Failed */ + dm_report_EIO(m); /* Failed */ + return DM_MAPIO_KILL; } else if (test_bit(MPATHF_QUEUE_IO, &m->flags) || test_bit(MPATHF_PG_INIT_REQUIRED, &m->flags)) { if (pg_init_all_paths(m)) @@ -558,7 +558,8 @@ static int __multipath_map_bio(struct multipath *m, struct bio *bio, struct dm_m if (!pgpath) { if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) return DM_MAPIO_REQUEUE; - return dm_report_EIO(m); + dm_report_EIO(m); + return -EIO; } mpio->pgpath = pgpath; @@ -1493,7 +1494,7 @@ static int multipath_end_io(struct dm_target *ti, struct request *clone, if (atomic_read(&m->nr_valid_paths) == 0 && !test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) { if (error == -EIO) - error = dm_report_EIO(m); + dm_report_EIO(m); /* complete with the original error */ r = DM_ENDIO_DONE; } @@ -1524,8 +1525,10 @@ static int do_end_io_bio(struct multipath *m, struct bio *clone, fail_path(mpio->pgpath); if (atomic_read(&m->nr_valid_paths) == 0 && - !test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) - return dm_report_EIO(m); + !test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) { + dm_report_EIO(m); + return -EIO; + } /* Queue for the daemon to resubmit */ dm_bio_restore(get_bio_details_from_bio(clone), clone); diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c index 2af27026aa2e..b639fa7246ee 100644 --- a/drivers/md/dm-rq.c +++ b/drivers/md/dm-rq.c @@ -507,6 +507,7 @@ static int map_request(struct dm_rq_target_io *tio) case DM_MAPIO_KILL: /* The target wants to complete the I/O */ dm_kill_unmapped_request(rq, -EIO); + break; default: DMWARN("unimplemented target map return value: %d", r); BUG(); diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c index 0f0251d0d337..d31d18d9727c 100644 --- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c @@ -484,11 +484,11 @@ static int __write_initial_superblock(struct dm_pool_metadata *pmd) if (r < 0) return r; - r = save_sm_roots(pmd); + r = dm_tm_pre_commit(pmd->tm); if (r < 0) return r; - r = dm_tm_pre_commit(pmd->tm); + r = save_sm_roots(pmd); if (r < 0) return r; diff --git a/drivers/md/md.c b/drivers/md/md.c index 82f798be964f..10367ffe92e3 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -8022,18 +8022,15 @@ EXPORT_SYMBOL(md_write_end); * may proceed without blocking. It is important to call this before * attempting a GFP_KERNEL allocation while holding the mddev lock. * Must be called with mddev_lock held. - * - * In the ->external case MD_SB_CHANGE_PENDING can not be cleared until mddev->lock - * is dropped, so return -EAGAIN after notifying userspace. */ -int md_allow_write(struct mddev *mddev) +void md_allow_write(struct mddev *mddev) { if (!mddev->pers) - return 0; + return; if (mddev->ro) - return 0; + return; if (!mddev->pers->sync_request) - return 0; + return; spin_lock(&mddev->lock); if (mddev->in_sync) { @@ -8046,13 +8043,12 @@ int md_allow_write(struct mddev *mddev) spin_unlock(&mddev->lock); md_update_sb(mddev, 0); sysfs_notify_dirent_safe(mddev->sysfs_state); + /* wait for the dirty state to be recorded in the metadata */ + wait_event(mddev->sb_wait, + !test_bit(MD_SB_CHANGE_CLEAN, &mddev->sb_flags) && + !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags)); } else spin_unlock(&mddev->lock); - - if (test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags)) - return -EAGAIN; - else - return 0; } EXPORT_SYMBOL_GPL(md_allow_write); diff --git a/drivers/md/md.h b/drivers/md/md.h index 4e75d121bfcc..11f15146ce51 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -665,7 +665,7 @@ extern int sync_page_io(struct md_rdev *rdev, sector_t sector, int size, bool metadata_op); extern void md_do_sync(struct md_thread *thread); extern void md_new_event(struct mddev *mddev); -extern int md_allow_write(struct mddev *mddev); +extern void md_allow_write(struct mddev *mddev); extern void md_wait_for_blocked_rdev(struct md_rdev *rdev, struct mddev *mddev); extern void md_set_array_sectors(struct mddev *mddev, sector_t array_sectors); extern int md_check_no_bitmap(struct mddev *mddev); diff --git a/drivers/md/persistent-data/dm-space-map-disk.c b/drivers/md/persistent-data/dm-space-map-disk.c index ebb280a14325..32adf6b4a9c7 100644 --- a/drivers/md/persistent-data/dm-space-map-disk.c +++ b/drivers/md/persistent-data/dm-space-map-disk.c @@ -142,10 +142,23 @@ static int sm_disk_inc_block(struct dm_space_map *sm, dm_block_t b) static int sm_disk_dec_block(struct dm_space_map *sm, dm_block_t b) { + int r; + uint32_t old_count; enum allocation_event ev; struct sm_disk *smd = container_of(sm, struct sm_disk, sm); - return sm_ll_dec(&smd->ll, b, &ev); + r = sm_ll_dec(&smd->ll, b, &ev); + if (!r && (ev == SM_FREE)) { + /* + * It's only free if it's also free in the last + * transaction. + */ + r = sm_ll_lookup(&smd->old_ll, b, &old_count); + if (!r && !old_count) + smd->nr_allocated_this_transaction--; + } + + return r; } static int sm_disk_new_block(struct dm_space_map *sm, dm_block_t *b) diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 84e58596594d..d6c0bc76e837 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -385,7 +385,7 @@ static int raid0_run(struct mddev *mddev) blk_queue_max_hw_sectors(mddev->queue, mddev->chunk_sectors); blk_queue_max_write_same_sectors(mddev->queue, mddev->chunk_sectors); blk_queue_max_write_zeroes_sectors(mddev->queue, mddev->chunk_sectors); - blk_queue_max_discard_sectors(mddev->queue, mddev->chunk_sectors); + blk_queue_max_discard_sectors(mddev->queue, UINT_MAX); blk_queue_io_min(mddev->queue, mddev->chunk_sectors << 9); blk_queue_io_opt(mddev->queue, @@ -459,6 +459,95 @@ static inline int is_io_in_chunk_boundary(struct mddev *mddev, } } +static void raid0_handle_discard(struct mddev *mddev, struct bio *bio) +{ + struct r0conf *conf = mddev->private; + struct strip_zone *zone; + sector_t start = bio->bi_iter.bi_sector; + sector_t end; + unsigned int stripe_size; + sector_t first_stripe_index, last_stripe_index; + sector_t start_disk_offset; + unsigned int start_disk_index; + sector_t end_disk_offset; + unsigned int end_disk_index; + unsigned int disk; + + zone = find_zone(conf, &start); + + if (bio_end_sector(bio) > zone->zone_end) { + struct bio *split = bio_split(bio, + zone->zone_end - bio->bi_iter.bi_sector, GFP_NOIO, + mddev->bio_set); + bio_chain(split, bio); + generic_make_request(bio); + bio = split; + end = zone->zone_end; + } else + end = bio_end_sector(bio); + + if (zone != conf->strip_zone) + end = end - zone[-1].zone_end; + + /* Now start and end is the offset in zone */ + stripe_size = zone->nb_dev * mddev->chunk_sectors; + + first_stripe_index = start; + sector_div(first_stripe_index, stripe_size); + last_stripe_index = end; + sector_div(last_stripe_index, stripe_size); + + start_disk_index = (int)(start - first_stripe_index * stripe_size) / + mddev->chunk_sectors; + start_disk_offset = ((int)(start - first_stripe_index * stripe_size) % + mddev->chunk_sectors) + + first_stripe_index * mddev->chunk_sectors; + end_disk_index = (int)(end - last_stripe_index * stripe_size) / + mddev->chunk_sectors; + end_disk_offset = ((int)(end - last_stripe_index * stripe_size) % + mddev->chunk_sectors) + + last_stripe_index * mddev->chunk_sectors; + + for (disk = 0; disk < zone->nb_dev; disk++) { + sector_t dev_start, dev_end; + struct bio *discard_bio = NULL; + struct md_rdev *rdev; + + if (disk < start_disk_index) + dev_start = (first_stripe_index + 1) * + mddev->chunk_sectors; + else if (disk > start_disk_index) + dev_start = first_stripe_index * mddev->chunk_sectors; + else + dev_start = start_disk_offset; + + if (disk < end_disk_index) + dev_end = (last_stripe_index + 1) * mddev->chunk_sectors; + else if (disk > end_disk_index) + dev_end = last_stripe_index * mddev->chunk_sectors; + else + dev_end = end_disk_offset; + + if (dev_end <= dev_start) + continue; + + rdev = conf->devlist[(zone - conf->strip_zone) * + conf->strip_zone[0].nb_dev + disk]; + if (__blkdev_issue_discard(rdev->bdev, + dev_start + zone->dev_start + rdev->data_offset, + dev_end - dev_start, GFP_NOIO, 0, &discard_bio) || + !discard_bio) + continue; + bio_chain(discard_bio, bio); + if (mddev->gendisk) + trace_block_bio_remap(bdev_get_queue(rdev->bdev), + discard_bio, disk_devt(mddev->gendisk), + bio->bi_iter.bi_sector); + generic_make_request(discard_bio); + } + bio_endio(bio); +} + static void raid0_make_request(struct mddev *mddev, struct bio *bio) { struct strip_zone *zone; @@ -473,6 +562,11 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio) return; } + if (unlikely((bio_op(bio) == REQ_OP_DISCARD))) { + raid0_handle_discard(mddev, bio); + return; + } + bio_sector = bio->bi_iter.bi_sector; sector = bio_sector; chunk_sects = mddev->chunk_sectors; @@ -498,19 +592,13 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio) bio->bi_iter.bi_sector = sector + zone->dev_start + tmp_dev->data_offset; - if (unlikely((bio_op(bio) == REQ_OP_DISCARD) && - !blk_queue_discard(bdev_get_queue(bio->bi_bdev)))) { - /* Just ignore it */ - bio_endio(bio); - } else { - if (mddev->gendisk) - trace_block_bio_remap(bdev_get_queue(bio->bi_bdev), - bio, disk_devt(mddev->gendisk), - bio_sector); - mddev_check_writesame(mddev, bio); - mddev_check_write_zeroes(mddev, bio); - generic_make_request(bio); - } + if (mddev->gendisk) + trace_block_bio_remap(bdev_get_queue(bio->bi_bdev), + bio, disk_devt(mddev->gendisk), + bio_sector); + mddev_check_writesame(mddev, bio); + mddev_check_write_zeroes(mddev, bio); + generic_make_request(bio); } static void raid0_status(struct seq_file *seq, struct mddev *mddev) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 7ed59351fe97..af5056d56878 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -666,8 +666,11 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect break; } continue; - } else + } else { + if ((sectors > best_good_sectors) && (best_disk >= 0)) + best_disk = -1; best_good_sectors = sectors; + } if (best_disk >= 0) /* At least two disks to choose from so failfast is OK */ @@ -1529,17 +1532,16 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio, plug = container_of(cb, struct raid1_plug_cb, cb); else plug = NULL; - spin_lock_irqsave(&conf->device_lock, flags); if (plug) { bio_list_add(&plug->pending, mbio); plug->pending_cnt++; } else { + spin_lock_irqsave(&conf->device_lock, flags); bio_list_add(&conf->pending_bio_list, mbio); conf->pending_count++; - } - spin_unlock_irqrestore(&conf->device_lock, flags); - if (!plug) + spin_unlock_irqrestore(&conf->device_lock, flags); md_wakeup_thread(mddev->thread); + } } r1_bio_write_done(r1_bio); @@ -3197,7 +3199,7 @@ static int raid1_reshape(struct mddev *mddev) struct r1conf *conf = mddev->private; int cnt, raid_disks; unsigned long flags; - int d, d2, err; + int d, d2; /* Cannot change chunk_size, layout, or level */ if (mddev->chunk_sectors != mddev->new_chunk_sectors || @@ -3209,11 +3211,8 @@ static int raid1_reshape(struct mddev *mddev) return -EINVAL; } - if (!mddev_is_clustered(mddev)) { - err = md_allow_write(mddev); - if (err) - return err; - } + if (!mddev_is_clustered(mddev)) + md_allow_write(mddev); raid_disks = mddev->raid_disks + mddev->delta_disks; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 6b86a0032cf8..4343d7ff9916 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1282,17 +1282,16 @@ static void raid10_write_one_disk(struct mddev *mddev, struct r10bio *r10_bio, plug = container_of(cb, struct raid10_plug_cb, cb); else plug = NULL; - spin_lock_irqsave(&conf->device_lock, flags); if (plug) { bio_list_add(&plug->pending, mbio); plug->pending_cnt++; } else { + spin_lock_irqsave(&conf->device_lock, flags); bio_list_add(&conf->pending_bio_list, mbio); conf->pending_count++; - } - spin_unlock_irqrestore(&conf->device_lock, flags); - if (!plug) + spin_unlock_irqrestore(&conf->device_lock, flags); md_wakeup_thread(mddev->thread); + } } static void raid10_write_request(struct mddev *mddev, struct bio *bio, diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c index 26ba09282e7c..4c00bc248287 100644 --- a/drivers/md/raid5-cache.c +++ b/drivers/md/raid5-cache.c @@ -24,6 +24,7 @@ #include "md.h" #include "raid5.h" #include "bitmap.h" +#include "raid5-log.h" /* * metadata/data stored in disk with 4k size unit (a block) regardless @@ -622,20 +623,30 @@ static void r5l_do_submit_io(struct r5l_log *log, struct r5l_io_unit *io) __r5l_set_io_unit_state(io, IO_UNIT_IO_START); spin_unlock_irqrestore(&log->io_list_lock, flags); + /* + * In case of journal device failures, submit_bio will get error + * and calls endio, then active stripes will continue write + * process. Therefore, it is not necessary to check Faulty bit + * of journal device here. + * + * We can't check split_bio after current_bio is submitted. If + * io->split_bio is null, after current_bio is submitted, current_bio + * might already be completed and the io_unit is freed. We submit + * split_bio first to avoid the issue. + */ + if (io->split_bio) { + if (io->has_flush) + io->split_bio->bi_opf |= REQ_PREFLUSH; + if (io->has_fua) + io->split_bio->bi_opf |= REQ_FUA; + submit_bio(io->split_bio); + } + if (io->has_flush) io->current_bio->bi_opf |= REQ_PREFLUSH; if (io->has_fua) io->current_bio->bi_opf |= REQ_FUA; submit_bio(io->current_bio); - - if (!io->split_bio) - return; - - if (io->has_flush) - io->split_bio->bi_opf |= REQ_PREFLUSH; - if (io->has_fua) - io->split_bio->bi_opf |= REQ_FUA; - submit_bio(io->split_bio); } /* deferred io_unit will be dispatched here */ @@ -670,6 +681,11 @@ static void r5c_disable_writeback_async(struct work_struct *work) return; pr_info("md/raid:%s: Disabling writeback cache for degraded array.\n", mdname(mddev)); + + /* wait superblock change before suspend */ + wait_event(mddev->sb_wait, + !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags)); + mddev_suspend(mddev); log->r5c_journal_mode = R5C_JOURNAL_MODE_WRITE_THROUGH; mddev_resume(mddev); @@ -2621,8 +2637,11 @@ int r5c_try_caching_write(struct r5conf *conf, * When run in degraded mode, array is set to write-through mode. * This check helps drain pending write safely in the transition to * write-through mode. + * + * When a stripe is syncing, the write is also handled in write + * through mode. */ - if (s->failed) { + if (s->failed || test_bit(STRIPE_SYNCING, &sh->state)) { r5c_make_stripe_write_out(sh); return -EAGAIN; } @@ -2825,6 +2844,9 @@ void r5c_finish_stripe_write_out(struct r5conf *conf, } r5l_append_flush_payload(log, sh->sector); + /* stripe is flused to raid disks, we can do resync now */ + if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state)) + set_bit(STRIPE_HANDLE, &sh->state); } int r5c_cache_data(struct r5l_log *log, struct stripe_head *sh) @@ -2973,7 +2995,7 @@ ioerr: return ret; } -void r5c_update_on_rdev_error(struct mddev *mddev) +void r5c_update_on_rdev_error(struct mddev *mddev, struct md_rdev *rdev) { struct r5conf *conf = mddev->private; struct r5l_log *log = conf->log; @@ -2981,7 +3003,8 @@ void r5c_update_on_rdev_error(struct mddev *mddev) if (!log) return; - if (raid5_calc_degraded(conf) > 0 && + if ((raid5_calc_degraded(conf) > 0 || + test_bit(Journal, &rdev->flags)) && conf->log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_BACK) schedule_work(&log->disable_writeback_work); } diff --git a/drivers/md/raid5-log.h b/drivers/md/raid5-log.h index 27097101ccca..328d67aedda4 100644 --- a/drivers/md/raid5-log.h +++ b/drivers/md/raid5-log.h @@ -28,7 +28,8 @@ extern void r5c_flush_cache(struct r5conf *conf, int num); extern void r5c_check_stripe_cache_usage(struct r5conf *conf); extern void r5c_check_cached_full_stripe(struct r5conf *conf); extern struct md_sysfs_entry r5c_journal_mode; -extern void r5c_update_on_rdev_error(struct mddev *mddev); +extern void r5c_update_on_rdev_error(struct mddev *mddev, + struct md_rdev *rdev); extern bool r5c_big_stripe_cached(struct r5conf *conf, sector_t sect); extern struct dma_async_tx_descriptor * diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 2e38cfac5b1d..9c4f7659f8b1 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -103,8 +103,7 @@ static inline void unlock_device_hash_lock(struct r5conf *conf, int hash) static inline void lock_all_device_hash_locks_irq(struct r5conf *conf) { int i; - local_irq_disable(); - spin_lock(conf->hash_locks); + spin_lock_irq(conf->hash_locks); for (i = 1; i < NR_STRIPE_HASH_LOCKS; i++) spin_lock_nest_lock(conf->hash_locks + i, conf->hash_locks); spin_lock(&conf->device_lock); @@ -114,9 +113,9 @@ static inline void unlock_all_device_hash_locks_irq(struct r5conf *conf) { int i; spin_unlock(&conf->device_lock); - for (i = NR_STRIPE_HASH_LOCKS; i; i--) - spin_unlock(conf->hash_locks + i - 1); - local_irq_enable(); + for (i = NR_STRIPE_HASH_LOCKS - 1; i; i--) + spin_unlock(conf->hash_locks + i); + spin_unlock_irq(conf->hash_locks); } /* Find first data disk in a raid6 stripe */ @@ -234,11 +233,15 @@ static void do_release_stripe(struct r5conf *conf, struct stripe_head *sh, if (test_bit(R5_InJournal, &sh->dev[i].flags)) injournal++; /* - * When quiesce in r5c write back, set STRIPE_HANDLE for stripes with - * data in journal, so they are not released to cached lists + * In the following cases, the stripe cannot be released to cached + * lists. Therefore, we make the stripe write out and set + * STRIPE_HANDLE: + * 1. when quiesce in r5c write back; + * 2. when resync is requested fot the stripe. */ - if (conf->quiesce && r5c_is_writeback(conf->log) && - !test_bit(STRIPE_HANDLE, &sh->state) && injournal != 0) { + if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state) || + (conf->quiesce && r5c_is_writeback(conf->log) && + !test_bit(STRIPE_HANDLE, &sh->state) && injournal != 0)) { if (test_bit(STRIPE_R5C_CACHING, &sh->state)) r5c_make_stripe_write_out(sh); set_bit(STRIPE_HANDLE, &sh->state); @@ -714,12 +717,11 @@ static bool is_full_stripe_write(struct stripe_head *sh) static void lock_two_stripes(struct stripe_head *sh1, struct stripe_head *sh2) { - local_irq_disable(); if (sh1 > sh2) { - spin_lock(&sh2->stripe_lock); + spin_lock_irq(&sh2->stripe_lock); spin_lock_nested(&sh1->stripe_lock, 1); } else { - spin_lock(&sh1->stripe_lock); + spin_lock_irq(&sh1->stripe_lock); spin_lock_nested(&sh2->stripe_lock, 1); } } @@ -727,8 +729,7 @@ static void lock_two_stripes(struct stripe_head *sh1, struct stripe_head *sh2) static void unlock_two_stripes(struct stripe_head *sh1, struct stripe_head *sh2) { spin_unlock(&sh1->stripe_lock); - spin_unlock(&sh2->stripe_lock); - local_irq_enable(); + spin_unlock_irq(&sh2->stripe_lock); } /* Only freshly new full stripe normal write stripe can be added to a batch list */ @@ -2312,14 +2313,12 @@ static int resize_stripes(struct r5conf *conf, int newsize) struct stripe_head *osh, *nsh; LIST_HEAD(newstripes); struct disk_info *ndisks; - int err; + int err = 0; struct kmem_cache *sc; int i; int hash, cnt; - err = md_allow_write(conf->mddev); - if (err) - return err; + md_allow_write(conf->mddev); /* Step 1 */ sc = kmem_cache_create(conf->cache_name[1-conf->active_name], @@ -2694,7 +2693,7 @@ static void raid5_error(struct mddev *mddev, struct md_rdev *rdev) bdevname(rdev->bdev, b), mdname(mddev), conf->raid_disks - mddev->degraded); - r5c_update_on_rdev_error(mddev); + r5c_update_on_rdev_error(mddev, rdev); } /* @@ -3055,6 +3054,11 @@ sector_t raid5_compute_blocknr(struct stripe_head *sh, int i, int previous) * When LOG_CRITICAL, stripes with injournal == 0 will be sent to * no_space_stripes list. * + * 3. during journal failure + * In journal failure, we try to flush all cached data to raid disks + * based on data in stripe cache. The array is read-only to upper + * layers, so we would skip all pending writes. + * */ static inline bool delay_towrite(struct r5conf *conf, struct r5dev *dev, @@ -3068,6 +3072,9 @@ static inline bool delay_towrite(struct r5conf *conf, if (test_bit(R5C_LOG_CRITICAL, &conf->cache_state) && s->injournal > 0) return true; + /* case 3 above */ + if (s->log_failed && s->injournal) + return true; return false; } @@ -4653,8 +4660,13 @@ static void handle_stripe(struct stripe_head *sh) if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state) && !sh->batch_head) { spin_lock(&sh->stripe_lock); - /* Cannot process 'sync' concurrently with 'discard' */ - if (!test_bit(STRIPE_DISCARD, &sh->state) && + /* + * Cannot process 'sync' concurrently with 'discard'. + * Flush data in r5cache before 'sync'. + */ + if (!test_bit(STRIPE_R5C_PARTIAL_STRIPE, &sh->state) && + !test_bit(STRIPE_R5C_FULL_STRIPE, &sh->state) && + !test_bit(STRIPE_DISCARD, &sh->state) && test_and_clear_bit(STRIPE_SYNC_REQUESTED, &sh->state)) { set_bit(STRIPE_SYNCING, &sh->state); clear_bit(STRIPE_INSYNC, &sh->state); @@ -4701,10 +4713,15 @@ static void handle_stripe(struct stripe_head *sh) " to_write=%d failed=%d failed_num=%d,%d\n", s.locked, s.uptodate, s.to_read, s.to_write, s.failed, s.failed_num[0], s.failed_num[1]); - /* check if the array has lost more than max_degraded devices and, + /* + * check if the array has lost more than max_degraded devices and, * if so, some requests might need to be failed. + * + * When journal device failed (log_failed), we will only process + * the stripe if there is data need write to raid disks */ - if (s.failed > conf->max_degraded || s.log_failed) { + if (s.failed > conf->max_degraded || + (s.log_failed && s.injournal == 0)) { sh->check_state = 0; sh->reconstruct_state = 0; break_stripe_batch_list(sh, 0); @@ -5277,8 +5294,10 @@ static struct stripe_head *__get_priority_stripe(struct r5conf *conf, int group) struct stripe_head *sh, *tmp; struct list_head *handle_list = NULL; struct r5worker_group *wg; - bool second_try = !r5c_is_writeback(conf->log); - bool try_loprio = test_bit(R5C_LOG_TIGHT, &conf->cache_state); + bool second_try = !r5c_is_writeback(conf->log) && + !r5l_log_disk_error(conf); + bool try_loprio = test_bit(R5C_LOG_TIGHT, &conf->cache_state) || + r5l_log_disk_error(conf); again: wg = NULL; @@ -6313,7 +6332,6 @@ int raid5_set_cache_size(struct mddev *mddev, int size) { struct r5conf *conf = mddev->private; - int err; if (size <= 16 || size > 32768) return -EINVAL; @@ -6325,10 +6343,7 @@ raid5_set_cache_size(struct mddev *mddev, int size) ; mutex_unlock(&conf->cache_size_mutex); - - err = md_allow_write(mddev); - if (err) - return err; + md_allow_write(mddev); mutex_lock(&conf->cache_size_mutex); while (size > conf->max_nr_stripes) @@ -7530,7 +7545,9 @@ static int raid5_remove_disk(struct mddev *mddev, struct md_rdev *rdev) * neilb: there is no locking about new writes here, * so this cannot be safe. */ - if (atomic_read(&conf->active_stripes)) { + if (atomic_read(&conf->active_stripes) || + atomic_read(&conf->r5c_cached_full_stripes) || + atomic_read(&conf->r5c_cached_partial_stripes)) { return -EBUSY; } log_exit(conf); diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index bf0fe0137dfe..6d1b4b707cc2 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -512,7 +512,7 @@ static void gpmc_cs_show_timings(int cs, const char *desc) pr_info("gpmc cs%i access configuration:\n", cs); GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 4, 4, "time-para-granularity"); GPMC_GET_RAW(GPMC_CS_CONFIG1, 8, 9, "mux-add-data"); - GPMC_GET_RAW_MAX(GPMC_CS_CONFIG1, 12, 13, + GPMC_GET_RAW_SHIFT_MAX(GPMC_CS_CONFIG1, 12, 13, 1, GPMC_CONFIG1_DEVICESIZE_MAX, "device-width"); GPMC_GET_RAW(GPMC_CS_CONFIG1, 16, 17, "wait-pin"); GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 21, 21, "wait-on-write"); diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 2cba76e6fa3c..07bbd4cc1852 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -492,6 +492,7 @@ config ASPEED_LPC_CTRL config PCI_ENDPOINT_TEST depends on PCI + select CRC32 tristate "PCI Endpoint Test driver" ---help--- Enable this configuration option to enable the host side test driver diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 19581d783d8e..d034d8cd7d22 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -849,6 +849,9 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip, mv88e6xxx_g1_stats_read(chip, reg, &low); if (s->sizeof_stat == 8) mv88e6xxx_g1_stats_read(chip, reg + 1, &high); + break; + default: + return UINT64_MAX; } value = (((u64)high) << 16) | low; return value; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c index 4ee15ff06a44..faeb4935ef3e 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c @@ -200,29 +200,18 @@ err_exit: static int hw_atl_a0_hw_offload_set(struct aq_hw_s *self, struct aq_nic_cfg_s *aq_nic_cfg) { - int err = 0; - /* TX checksums offloads*/ tpo_ipv4header_crc_offload_en_set(self, 1); tpo_tcp_udp_crc_offload_en_set(self, 1); - if (err < 0) - goto err_exit; /* RX checksums offloads*/ rpo_ipv4header_crc_offload_en_set(self, 1); rpo_tcp_udp_crc_offload_en_set(self, 1); - if (err < 0) - goto err_exit; /* LSO offloads*/ tdm_large_send_offload_en_set(self, 0xFFFFFFFFU); - if (err < 0) - goto err_exit; - - err = aq_hw_err_from_flags(self); -err_exit: - return err; + return aq_hw_err_from_flags(self); } static int hw_atl_a0_hw_init_tx_path(struct aq_hw_s *self) diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c index 42150708191d..1bceb7358e5c 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c @@ -200,25 +200,18 @@ err_exit: static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self, struct aq_nic_cfg_s *aq_nic_cfg) { - int err = 0; unsigned int i; /* TX checksums offloads*/ tpo_ipv4header_crc_offload_en_set(self, 1); tpo_tcp_udp_crc_offload_en_set(self, 1); - if (err < 0) - goto err_exit; /* RX checksums offloads*/ rpo_ipv4header_crc_offload_en_set(self, 1); rpo_tcp_udp_crc_offload_en_set(self, 1); - if (err < 0) - goto err_exit; /* LSO offloads*/ tdm_large_send_offload_en_set(self, 0xFFFFFFFFU); - if (err < 0) - goto err_exit; /* LRO offloads */ { @@ -245,10 +238,7 @@ static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self, rpo_lro_en_set(self, aq_nic_cfg->is_lro ? 0xFFFFFFFFU : 0U); } - err = aq_hw_err_from_flags(self); - -err_exit: - return err; + return aq_hw_err_from_flags(self); } static int hw_atl_b0_hw_init_tx_path(struct aq_hw_s *self) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index b56c54d68d5e..03f55daecb20 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -7630,8 +7630,6 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->min_mtu = ETH_ZLEN; dev->max_mtu = BNXT_MAX_MTU; - bnxt_dcb_init(bp); - #ifdef CONFIG_BNXT_SRIOV init_waitqueue_head(&bp->sriov_cfg_wait); #endif @@ -7669,6 +7667,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) bnxt_hwrm_func_qcfg(bp); bnxt_hwrm_port_led_qcaps(bp); bnxt_ethtool_init(bp); + bnxt_dcb_init(bp); bnxt_set_rx_skb_mode(bp, false); bnxt_set_tpa_flags(bp); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c index 46de2f8ff024..5c6dd0ce209f 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c @@ -553,8 +553,10 @@ static u8 bnxt_dcbnl_setdcbx(struct net_device *dev, u8 mode) if ((mode & DCB_CAP_DCBX_VER_CEE) || !(mode & DCB_CAP_DCBX_VER_IEEE)) return 1; - if ((mode & DCB_CAP_DCBX_HOST) && BNXT_VF(bp)) - return 1; + if (mode & DCB_CAP_DCBX_HOST) { + if (BNXT_VF(bp) || (bp->flags & BNXT_FLAG_FW_LLDP_AGENT)) + return 1; + } if (mode == bp->dcbx_cap) return 0; diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h index fa376444e57c..3549d3876278 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h @@ -37,7 +37,7 @@ #define T4FW_VERSION_MAJOR 0x01 #define T4FW_VERSION_MINOR 0x10 -#define T4FW_VERSION_MICRO 0x21 +#define T4FW_VERSION_MICRO 0x2B #define T4FW_VERSION_BUILD 0x00 #define T4FW_MIN_VERSION_MAJOR 0x01 @@ -46,7 +46,7 @@ #define T5FW_VERSION_MAJOR 0x01 #define T5FW_VERSION_MINOR 0x10 -#define T5FW_VERSION_MICRO 0x21 +#define T5FW_VERSION_MICRO 0x2B #define T5FW_VERSION_BUILD 0x00 #define T5FW_MIN_VERSION_MAJOR 0x00 @@ -55,7 +55,7 @@ #define T6FW_VERSION_MAJOR 0x01 #define T6FW_VERSION_MINOR 0x10 -#define T6FW_VERSION_MICRO 0x21 +#define T6FW_VERSION_MICRO 0x2B #define T6FW_VERSION_BUILD 0x00 #define T6FW_MIN_VERSION_MAJOR 0x00 diff --git a/drivers/net/ethernet/faraday/ftmac100.c b/drivers/net/ethernet/faraday/ftmac100.c index 6ac336b546e6..1536356e2ea8 100644 --- a/drivers/net/ethernet/faraday/ftmac100.c +++ b/drivers/net/ethernet/faraday/ftmac100.c @@ -1174,11 +1174,17 @@ static int ftmac100_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id ftmac100_of_ids[] = { + { .compatible = "andestech,atmac100" }, + { } +}; + static struct platform_driver ftmac100_driver = { .probe = ftmac100_probe, .remove = ftmac100_remove, .driver = { .name = DRV_NAME, + .of_match_table = ftmac100_of_ids }, }; @@ -1202,3 +1208,4 @@ module_exit(ftmac100_exit); MODULE_AUTHOR("Po-Yu Chuang <ratbert@faraday-tech.com>"); MODULE_DESCRIPTION("FTMAC100 driver"); MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(of, ftmac100_of_ids); diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 703205475524..83aab1e4c8c8 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -2862,12 +2862,10 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev) int port = 0; if (msi_x) { - int nreq = dev->caps.num_ports * num_online_cpus() + 1; - - nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs, - nreq); - if (nreq > MAX_MSIX) - nreq = MAX_MSIX; + int nreq = min3(dev->caps.num_ports * + (int)num_online_cpus() + 1, + dev->caps.num_eqs - dev->caps.reserved_eqs, + MAX_MSIX); entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL); if (!entries) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig index fc52d742b7f7..27251a78075c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig +++ b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig @@ -13,7 +13,7 @@ config MLX5_CORE config MLX5_CORE_EN bool "Mellanox Technologies ConnectX-4 Ethernet support" - depends on NETDEVICES && ETHERNET && PCI && MLX5_CORE + depends on NETDEVICES && ETHERNET && INET && PCI && MLX5_CORE depends on IPV6=y || IPV6=n || MLX5_CORE=m imply PTP_1588_CLOCK default n diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 0099a3e397bc..2fd044b23875 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -1003,7 +1003,7 @@ int mlx5e_create_direct_tirs(struct mlx5e_priv *priv); void mlx5e_destroy_direct_tirs(struct mlx5e_priv *priv); void mlx5e_destroy_rqt(struct mlx5e_priv *priv, struct mlx5e_rqt *rqt); -int mlx5e_create_ttc_table(struct mlx5e_priv *priv, u32 underlay_qpn); +int mlx5e_create_ttc_table(struct mlx5e_priv *priv); void mlx5e_destroy_ttc_table(struct mlx5e_priv *priv); int mlx5e_create_tis(struct mlx5_core_dev *mdev, int tc, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index ce7b09d72ff6..8209affa75c3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -794,7 +794,6 @@ static void get_supported(u32 eth_proto_cap, ptys2ethtool_supported_port(link_ksettings, eth_proto_cap); ptys2ethtool_supported_link(supported, eth_proto_cap); ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Pause); - ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Asym_Pause); } static void get_advertising(u32 eth_proto_cap, u8 tx_pause, @@ -804,7 +803,7 @@ static void get_advertising(u32 eth_proto_cap, u8 tx_pause, unsigned long *advertising = link_ksettings->link_modes.advertising; ptys2ethtool_adver_link(advertising, eth_proto_cap); - if (tx_pause) + if (rx_pause) ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Pause); if (tx_pause ^ rx_pause) ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Asym_Pause); @@ -849,6 +848,8 @@ static int mlx5e_get_link_ksettings(struct net_device *netdev, struct mlx5e_priv *priv = netdev_priv(netdev); struct mlx5_core_dev *mdev = priv->mdev; u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0}; + u32 rx_pause = 0; + u32 tx_pause = 0; u32 eth_proto_cap; u32 eth_proto_admin; u32 eth_proto_lp; @@ -871,11 +872,13 @@ static int mlx5e_get_link_ksettings(struct net_device *netdev, an_disable_admin = MLX5_GET(ptys_reg, out, an_disable_admin); an_status = MLX5_GET(ptys_reg, out, an_status); + mlx5_query_port_pause(mdev, &rx_pause, &tx_pause); + ethtool_link_ksettings_zero_link_mode(link_ksettings, supported); ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising); get_supported(eth_proto_cap, link_ksettings); - get_advertising(eth_proto_admin, 0, 0, link_ksettings); + get_advertising(eth_proto_admin, tx_pause, rx_pause, link_ksettings); get_speed_duplex(netdev, eth_proto_oper, link_ksettings); eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c index 576d6787b484..53ed58320a24 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c @@ -800,7 +800,7 @@ void mlx5e_destroy_ttc_table(struct mlx5e_priv *priv) mlx5e_destroy_flow_table(&ttc->ft); } -int mlx5e_create_ttc_table(struct mlx5e_priv *priv, u32 underlay_qpn) +int mlx5e_create_ttc_table(struct mlx5e_priv *priv) { struct mlx5e_ttc_table *ttc = &priv->fs.ttc; struct mlx5_flow_table_attr ft_attr = {}; @@ -810,7 +810,6 @@ int mlx5e_create_ttc_table(struct mlx5e_priv *priv, u32 underlay_qpn) ft_attr.max_fte = MLX5E_TTC_TABLE_SIZE; ft_attr.level = MLX5E_TTC_FT_LEVEL; ft_attr.prio = MLX5E_NIC_PRIO; - ft_attr.underlay_qpn = underlay_qpn; ft->t = mlx5_create_flow_table(priv->fs.ns, &ft_attr); if (IS_ERR(ft->t)) { @@ -1147,7 +1146,7 @@ int mlx5e_create_flow_steering(struct mlx5e_priv *priv) priv->netdev->hw_features &= ~NETIF_F_NTUPLE; } - err = mlx5e_create_ttc_table(priv, 0); + err = mlx5e_create_ttc_table(priv); if (err) { netdev_err(priv->netdev, "Failed to create ttc table, err=%d\n", err); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index a61b71b6fff3..41cd22a223dc 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -2976,7 +2976,7 @@ static int mlx5e_setup_tc(struct net_device *netdev, u8 tc) new_channels.params = priv->channels.params; new_channels.params.num_tc = tc ? tc : 1; - if (test_bit(MLX5E_STATE_OPENED, &priv->state)) { + if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) { priv->channels.params = new_channels.params; goto out; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c index 19e3d2fc2099..fcec7bedd3cd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c @@ -40,28 +40,25 @@ #include "eswitch.h" int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev, - struct mlx5_flow_table *ft) + struct mlx5_flow_table *ft, u32 underlay_qpn) { u32 in[MLX5_ST_SZ_DW(set_flow_table_root_in)] = {0}; u32 out[MLX5_ST_SZ_DW(set_flow_table_root_out)] = {0}; if ((MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_IB) && - ft->underlay_qpn == 0) + underlay_qpn == 0) return 0; MLX5_SET(set_flow_table_root_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ROOT); MLX5_SET(set_flow_table_root_in, in, table_type, ft->type); MLX5_SET(set_flow_table_root_in, in, table_id, ft->id); + MLX5_SET(set_flow_table_root_in, in, underlay_qpn, underlay_qpn); if (ft->vport) { MLX5_SET(set_flow_table_root_in, in, vport_number, ft->vport); MLX5_SET(set_flow_table_root_in, in, other_vport, 1); } - if ((MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_IB) && - ft->underlay_qpn != 0) - MLX5_SET(set_flow_table_root_in, in, underlay_qpn, ft->underlay_qpn); - return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h index 8fad80688536..0f98a7cf4877 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h @@ -71,7 +71,8 @@ int mlx5_cmd_delete_fte(struct mlx5_core_dev *dev, unsigned int index); int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev, - struct mlx5_flow_table *ft); + struct mlx5_flow_table *ft, + u32 underlay_qpn); int mlx5_cmd_fc_alloc(struct mlx5_core_dev *dev, u16 *id); int mlx5_cmd_fc_free(struct mlx5_core_dev *dev, u16 id); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index b8a176503d38..0e487e8ca634 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -650,7 +650,7 @@ static int update_root_ft_create(struct mlx5_flow_table *ft, struct fs_prio if (ft->level >= min_level) return 0; - err = mlx5_cmd_update_root_ft(root->dev, ft); + err = mlx5_cmd_update_root_ft(root->dev, ft, root->underlay_qpn); if (err) mlx5_core_warn(root->dev, "Update root flow table of id=%u failed\n", ft->id); @@ -818,8 +818,6 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa goto unlock_root; } - ft->underlay_qpn = ft_attr->underlay_qpn; - tree_init_node(&ft->node, 1, del_flow_table); log_table_sz = ft->max_fte ? ilog2(ft->max_fte) : 0; next_ft = find_next_chained_ft(fs_prio); @@ -1489,7 +1487,8 @@ static int update_root_ft_destroy(struct mlx5_flow_table *ft) new_root_ft = find_next_ft(ft); if (new_root_ft) { - int err = mlx5_cmd_update_root_ft(root->dev, new_root_ft); + int err = mlx5_cmd_update_root_ft(root->dev, new_root_ft, + root->underlay_qpn); if (err) { mlx5_core_warn(root->dev, "Update root flow table of id=%u failed\n", @@ -2062,3 +2061,21 @@ err: mlx5_cleanup_fs(dev); return err; } + +int mlx5_fs_add_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn) +{ + struct mlx5_flow_root_namespace *root = dev->priv.steering->root_ns; + + root->underlay_qpn = underlay_qpn; + return 0; +} +EXPORT_SYMBOL(mlx5_fs_add_rx_underlay_qpn); + +int mlx5_fs_remove_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn) +{ + struct mlx5_flow_root_namespace *root = dev->priv.steering->root_ns; + + root->underlay_qpn = 0; + return 0; +} +EXPORT_SYMBOL(mlx5_fs_remove_rx_underlay_qpn); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h index 81eafc7b9dd9..990acee6fb09 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h @@ -118,7 +118,6 @@ struct mlx5_flow_table { /* FWD rules that point on this flow table */ struct list_head fwd_rules; u32 flags; - u32 underlay_qpn; }; struct mlx5_fc_cache { @@ -195,6 +194,7 @@ struct mlx5_flow_root_namespace { struct mlx5_flow_table *root_ft; /* Should be held when chaining flow tables */ struct mutex chain_lock; + u32 underlay_qpn; }; int mlx5_init_fc_stats(struct mlx5_core_dev *dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib.c index 019c230da498..cc1858752e70 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib.c @@ -66,6 +66,10 @@ static void mlx5i_init(struct mlx5_core_dev *mdev, mlx5e_build_nic_params(mdev, &priv->channels.params, profile->max_nch(mdev)); + /* Override RQ params as IPoIB supports only LINKED LIST RQ for now */ + mlx5e_set_rq_type_params(mdev, &priv->channels.params, MLX5_WQ_TYPE_LINKED_LIST); + priv->channels.params.lro_en = false; + mutex_init(&priv->state_lock); netdev->hw_features |= NETIF_F_SG; @@ -156,6 +160,8 @@ out: static void mlx5i_destroy_underlay_qp(struct mlx5_core_dev *mdev, struct mlx5_core_qp *qp) { + mlx5_fs_remove_rx_underlay_qpn(mdev, qp->qpn); + mlx5_core_destroy_qp(mdev, qp); } @@ -170,6 +176,8 @@ static int mlx5i_init_tx(struct mlx5e_priv *priv) return err; } + mlx5_fs_add_rx_underlay_qpn(priv->mdev, ipriv->qp.qpn); + err = mlx5e_create_tis(priv->mdev, 0 /* tc */, ipriv->qp.qpn, &priv->tisn[0]); if (err) { mlx5_core_warn(priv->mdev, "create tis failed, %d\n", err); @@ -189,7 +197,6 @@ static void mlx5i_cleanup_tx(struct mlx5e_priv *priv) static int mlx5i_create_flow_steering(struct mlx5e_priv *priv) { - struct mlx5i_priv *ipriv = priv->ppriv; int err; priv->fs.ns = mlx5_get_flow_namespace(priv->mdev, @@ -205,7 +212,7 @@ static int mlx5i_create_flow_steering(struct mlx5e_priv *priv) priv->netdev->hw_features &= ~NETIF_F_NTUPLE; } - err = mlx5e_create_ttc_table(priv, ipriv->qp.qpn); + err = mlx5e_create_ttc_table(priv); if (err) { netdev_err(priv->netdev, "Failed to create ttc table, err=%d\n", err); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c index ea56f6ade6b4..5f0a7bc692a4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c @@ -199,10 +199,11 @@ static int mlxsw_sp_erif_entry_get(struct mlxsw_sp *mlxsw_sp, entry->counter_valid = false; entry->counter = 0; + entry->index = mlxsw_sp_rif_index(rif); + if (!counters_enabled) return 0; - entry->index = mlxsw_sp_rif_index(rif); err = mlxsw_sp_rif_counter_value_get(mlxsw_sp, rif, MLXSW_SP_RIF_COUNTER_EGRESS, &cnt); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 33cec1cc1642..9f89c4137d21 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -206,6 +206,9 @@ void mlxsw_sp_rif_counter_free(struct mlxsw_sp *mlxsw_sp, { unsigned int *p_counter_index; + if (!mlxsw_sp_rif_counter_valid_get(rif, dir)) + return; + p_counter_index = mlxsw_sp_rif_p_counter_get(rif, dir); if (WARN_ON(!p_counter_index)) return; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 0d8411f1f954..f4bb0c0b7c1d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -1497,8 +1497,7 @@ do_fdb_op: err = mlxsw_sp_port_fdb_uc_op(mlxsw_sp, local_port, mac, fid, adding, true); if (err) { - if (net_ratelimit()) - netdev_err(mlxsw_sp_port->dev, "Failed to set FDB entry\n"); + dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to set FDB entry\n"); return; } @@ -1558,8 +1557,7 @@ do_fdb_op: err = mlxsw_sp_port_fdb_uc_lag_op(mlxsw_sp, lag_id, mac, fid, lag_vid, adding, true); if (err) { - if (net_ratelimit()) - netdev_err(mlxsw_sp_port->dev, "Failed to set FDB entry\n"); + dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to set FDB entry\n"); return; } diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c index b8d5270359cd..e30676515529 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c @@ -247,7 +247,7 @@ nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu) cmd.req.arg3 = 0; if (recv_ctx->state == NX_HOST_CTX_STATE_ACTIVE) - netxen_issue_cmd(adapter, &cmd); + rcode = netxen_issue_cmd(adapter, &cmd); if (rcode != NX_RCODE_SUCCESS) return -EIO; diff --git a/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c b/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c index 67200c5498ab..0a8fde629991 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c +++ b/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c @@ -983,7 +983,7 @@ void qed_set_rfs_mode_disable(struct qed_hwfn *p_hwfn, memset(&camline, 0, sizeof(union gft_cam_line_union)); qed_wr(p_hwfn, p_ptt, PRS_REG_GFT_CAM + CAM_LINE_SIZE * pf_id, camline.cam_line_mapped.camline); - memset(&ramline, 0, sizeof(union gft_cam_line_union)); + memset(&ramline, 0, sizeof(ramline)); for (i = 0; i < RAM_LINE_SIZE / REG_SIZE; i++) { u32 hw_addr = PRS_REG_GFT_PROFILE_MASK_RAM; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 49bad00a0f8f..7245b1072518 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -37,8 +37,8 @@ #define _QLCNIC_LINUX_MAJOR 5 #define _QLCNIC_LINUX_MINOR 3 -#define _QLCNIC_LINUX_SUBVERSION 65 -#define QLCNIC_LINUX_VERSIONID "5.3.65" +#define _QLCNIC_LINUX_SUBVERSION 66 +#define QLCNIC_LINUX_VERSIONID "5.3.66" #define QLCNIC_DRV_IDC_VER 0x01 #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index 718bf58a7da6..4fb68797630e 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c @@ -3168,6 +3168,40 @@ int qlcnic_83xx_flash_read32(struct qlcnic_adapter *adapter, u32 flash_addr, return 0; } +void qlcnic_83xx_get_port_type(struct qlcnic_adapter *adapter) +{ + struct qlcnic_hardware_context *ahw = adapter->ahw; + struct qlcnic_cmd_args cmd; + u32 config; + int err; + + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_STATUS); + if (err) + return; + + err = qlcnic_issue_cmd(adapter, &cmd); + if (err) { + dev_info(&adapter->pdev->dev, + "Get Link Status Command failed: 0x%x\n", err); + goto out; + } else { + config = cmd.rsp.arg[3]; + + switch (QLC_83XX_SFP_MODULE_TYPE(config)) { + case QLC_83XX_MODULE_FIBRE_1000BASE_SX: + case QLC_83XX_MODULE_FIBRE_1000BASE_LX: + case QLC_83XX_MODULE_FIBRE_1000BASE_CX: + case QLC_83XX_MODULE_TP_1000BASE_T: + ahw->port_type = QLCNIC_GBE; + break; + default: + ahw->port_type = QLCNIC_XGBE; + } + } +out: + qlcnic_free_mbx_args(&cmd); +} + int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter) { u8 pci_func; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h index 3dfe8e27b51c..b75a81246856 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h @@ -637,6 +637,7 @@ void qlcnic_83xx_get_pauseparam(struct qlcnic_adapter *, int qlcnic_83xx_set_pauseparam(struct qlcnic_adapter *, struct ethtool_pauseparam *); int qlcnic_83xx_test_link(struct qlcnic_adapter *); +void qlcnic_83xx_get_port_type(struct qlcnic_adapter *adapter); int qlcnic_83xx_reg_test(struct qlcnic_adapter *); int qlcnic_83xx_get_regs_len(struct qlcnic_adapter *); int qlcnic_83xx_get_registers(struct qlcnic_adapter *, u32 *); diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c index 9a869c15d8bf..7f7deeaf1cf0 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c @@ -486,6 +486,9 @@ static int qlcnic_set_link_ksettings(struct net_device *dev, u32 ret = 0; struct qlcnic_adapter *adapter = netdev_priv(dev); + if (qlcnic_83xx_check(adapter)) + qlcnic_83xx_get_port_type(adapter); + if (adapter->ahw->port_type != QLCNIC_GBE) return -EOPNOTSUPP; diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c index 513e6c74e199..24ca7df15d07 100644 --- a/drivers/net/ethernet/qualcomm/qca_spi.c +++ b/drivers/net/ethernet/qualcomm/qca_spi.c @@ -296,8 +296,9 @@ qcaspi_receive(struct qcaspi *qca) /* Allocate rx SKB if we don't have one available. */ if (!qca->rx_skb) { - qca->rx_skb = netdev_alloc_skb(net_dev, - net_dev->mtu + VLAN_ETH_HLEN); + qca->rx_skb = netdev_alloc_skb_ip_align(net_dev, + net_dev->mtu + + VLAN_ETH_HLEN); if (!qca->rx_skb) { netdev_dbg(net_dev, "out of RX resources\n"); qca->stats.out_of_mem++; @@ -377,7 +378,7 @@ qcaspi_receive(struct qcaspi *qca) qca->rx_skb, qca->rx_skb->dev); qca->rx_skb->ip_summed = CHECKSUM_UNNECESSARY; netif_rx_ni(qca->rx_skb); - qca->rx_skb = netdev_alloc_skb(net_dev, + qca->rx_skb = netdev_alloc_skb_ip_align(net_dev, net_dev->mtu + VLAN_ETH_HLEN); if (!qca->rx_skb) { netdev_dbg(net_dev, "out of RX resources\n"); @@ -759,7 +760,8 @@ qcaspi_netdev_init(struct net_device *dev) if (!qca->rx_buffer) return -ENOBUFS; - qca->rx_skb = netdev_alloc_skb(dev, qca->net_dev->mtu + VLAN_ETH_HLEN); + qca->rx_skb = netdev_alloc_skb_ip_align(dev, qca->net_dev->mtu + + VLAN_ETH_HLEN); if (!qca->rx_skb) { kfree(qca->rx_buffer); netdev_info(qca->net_dev, "Failed to allocate RX sk_buff.\n"); diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index f68c4db656ed..2d686ccf971b 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -3220,7 +3220,8 @@ static int sh_eth_drv_probe(struct platform_device *pdev) /* MDIO bus init */ ret = sh_mdio_init(mdp, pd); if (ret) { - dev_err(&ndev->dev, "failed to initialise MDIO\n"); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "MDIO init failed: %d\n", ret); goto out_release; } diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index 7b916aa21bde..4d7fb8af880d 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -18,8 +18,12 @@ #include "mcdi.h" enum { - EFX_REV_SIENA_A0 = 0, - EFX_REV_HUNT_A0 = 1, + /* Revisions 0-2 were Falcon A0, A1 and B0 respectively. + * They are not supported by this driver but these revision numbers + * form part of the ethtool API for register dumping. + */ + EFX_REV_SIENA_A0 = 3, + EFX_REV_HUNT_A0 = 4, }; static inline int efx_nic_rev(struct efx_nic *efx) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index cd8c60132390..a74c481401c4 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -3725,7 +3725,7 @@ static void sysfs_display_ring(void *head, int size, int extend_desc, ep++; } else { seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", - i, (unsigned int)virt_to_phys(ep), + i, (unsigned int)virt_to_phys(p), le32_to_cpu(p->des0), le32_to_cpu(p->des1), le32_to_cpu(p->des2), le32_to_cpu(p->des3)); p++; diff --git a/drivers/net/ethernet/sun/ldmvsw.c b/drivers/net/ethernet/sun/ldmvsw.c index 5a90fed06260..5b56c24b6ed2 100644 --- a/drivers/net/ethernet/sun/ldmvsw.c +++ b/drivers/net/ethernet/sun/ldmvsw.c @@ -411,13 +411,14 @@ static int vsw_port_remove(struct vio_dev *vdev) if (port) { del_timer_sync(&port->vio.timer); + del_timer_sync(&port->clean_timer); napi_disable(&port->napi); + unregister_netdev(port->dev); list_del_rcu(&port->list); synchronize_rcu(); - del_timer_sync(&port->clean_timer); spin_lock_irqsave(&port->vp->lock, flags); sunvnet_port_rm_txq_common(port); spin_unlock_irqrestore(&port->vp->lock, flags); @@ -427,7 +428,6 @@ static int vsw_port_remove(struct vio_dev *vdev) dev_set_drvdata(&vdev->dev, NULL); - unregister_netdev(port->dev); free_netdev(port->dev); } diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c index 729a7da90b5b..e6222e535019 100644 --- a/drivers/net/ethernet/ti/netcp_core.c +++ b/drivers/net/ethernet/ti/netcp_core.c @@ -1353,9 +1353,10 @@ int netcp_txpipe_open(struct netcp_tx_pipe *tx_pipe) tx_pipe->dma_channel = knav_dma_open_channel(dev, tx_pipe->dma_chan_name, &config); - if (IS_ERR_OR_NULL(tx_pipe->dma_channel)) { + if (IS_ERR(tx_pipe->dma_channel)) { dev_err(dev, "failed opening tx chan(%s)\n", tx_pipe->dma_chan_name); + ret = PTR_ERR(tx_pipe->dma_channel); goto err; } @@ -1673,9 +1674,10 @@ static int netcp_setup_navigator_resources(struct net_device *ndev) netcp->rx_channel = knav_dma_open_channel(netcp->netcp_device->device, netcp->dma_chan_name, &config); - if (IS_ERR_OR_NULL(netcp->rx_channel)) { + if (IS_ERR(netcp->rx_channel)) { dev_err(netcp->ndev_dev, "failed opening rx chan(%s\n", netcp->dma_chan_name); + ret = PTR_ERR(netcp->rx_channel); goto fail; } diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index 897176fc5043..dd92950a4615 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c @@ -2651,7 +2651,6 @@ static int gbe_hwtstamp_set(struct gbe_intf *gbe_intf, struct ifreq *ifr) case HWTSTAMP_FILTER_NONE: cpts_rx_enable(cpts, 0); break; - case HWTSTAMP_FILTER_ALL: case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index 8716b8c07feb..6f3c805f7211 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c @@ -1077,7 +1077,7 @@ static int stir421x_patch_device(struct irda_usb_cb *self) * are "42101001.sb" or "42101002.sb" */ sprintf(stir421x_fw_name, "4210%4X.sb", - self->usbdev->descriptor.bcdDevice); + le16_to_cpu(self->usbdev->descriptor.bcdDevice)); ret = request_firmware(&fw, stir421x_fw_name, &self->usbdev->dev); if (ret < 0) return ret; diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index b34eaaae03fd..346ad2ff3998 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -789,10 +789,12 @@ static int macvlan_change_mtu(struct net_device *dev, int new_mtu) */ static struct lock_class_key macvlan_netdev_addr_lock_key; -#define ALWAYS_ON_FEATURES \ - (NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE | NETIF_F_LLTX | \ +#define ALWAYS_ON_OFFLOADS \ + (NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE | \ NETIF_F_GSO_ROBUST) +#define ALWAYS_ON_FEATURES (ALWAYS_ON_OFFLOADS | NETIF_F_LLTX) + #define MACVLAN_FEATURES \ (NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \ NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_LRO | \ @@ -827,6 +829,7 @@ static int macvlan_init(struct net_device *dev) dev->features |= ALWAYS_ON_FEATURES; dev->hw_features |= NETIF_F_LRO; dev->vlan_features = lowerdev->vlan_features & MACVLAN_FEATURES; + dev->vlan_features |= ALWAYS_ON_OFFLOADS; dev->gso_max_size = lowerdev->gso_max_size; dev->gso_max_segs = lowerdev->gso_max_segs; dev->hard_header_len = lowerdev->hard_header_len; diff --git a/drivers/net/phy/mdio-mux.c b/drivers/net/phy/mdio-mux.c index 963838d4fac1..599ce24c514f 100644 --- a/drivers/net/phy/mdio-mux.c +++ b/drivers/net/phy/mdio-mux.c @@ -122,10 +122,9 @@ int mdio_mux_init(struct device *dev, pb = devm_kzalloc(dev, sizeof(*pb), GFP_KERNEL); if (pb == NULL) { ret_val = -ENOMEM; - goto err_parent_bus; + goto err_pb_kz; } - pb->switch_data = data; pb->switch_fn = switch_fn; pb->current_child = -1; @@ -154,6 +153,7 @@ int mdio_mux_init(struct device *dev, cb->mii_bus = mdiobus_alloc(); if (!cb->mii_bus) { ret_val = -ENOMEM; + devm_kfree(dev, cb); of_node_put(child_bus_node); break; } @@ -170,7 +170,6 @@ int mdio_mux_init(struct device *dev, mdiobus_free(cb->mii_bus); devm_kfree(dev, cb); } else { - of_node_get(child_bus_node); cb->next = pb->children; pb->children = cb; } @@ -181,9 +180,11 @@ int mdio_mux_init(struct device *dev, return 0; } + devm_kfree(dev, pb); +err_pb_kz: /* balance the reference of_mdio_find_bus() took */ - put_device(&pb->mii_bus->dev); - + if (!mux_bus) + put_device(&parent_bus->dev); err_parent_bus: of_node_put(parent_bus_node); return ret_val; diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index a898e5c4ef1b..8e73f5f36e71 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -364,9 +364,6 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner) mutex_init(&bus->mdio_lock); - if (bus->reset) - bus->reset(bus); - /* de-assert bus level PHY GPIO resets */ if (bus->num_reset_gpios > 0) { bus->reset_gpiod = devm_kcalloc(&bus->dev, @@ -396,6 +393,9 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner) } } + if (bus->reset) + bus->reset(bus); + for (i = 0; i < PHY_MAX_ADDR; i++) { if ((bus->phy_mask & (1 << i)) == 0) { struct phy_device *phydev; diff --git a/drivers/net/usb/ch9200.c b/drivers/net/usb/ch9200.c index c4f1c363e24b..9df3c1ffff35 100644 --- a/drivers/net/usb/ch9200.c +++ b/drivers/net/usb/ch9200.c @@ -310,8 +310,8 @@ static int get_mac_address(struct usbnet *dev, unsigned char *data) int rd_mac_len = 0; netdev_dbg(dev->net, "get_mac_address:\n\tusbnet VID:%0x PID:%0x\n", - dev->udev->descriptor.idVendor, - dev->udev->descriptor.idProduct); + le16_to_cpu(dev->udev->descriptor.idVendor), + le16_to_cpu(dev->udev->descriptor.idProduct)); memset(mac_addr, 0, sizeof(mac_addr)); rd_mac_len = control_read(dev, REQUEST_READ, 0, diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index d7165767ca9d..8f923a147fa9 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -1196,6 +1196,8 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x1199, 0x9071, 10)}, /* Sierra Wireless MC74xx */ {QMI_FIXED_INTF(0x1199, 0x9079, 8)}, /* Sierra Wireless EM74xx */ {QMI_FIXED_INTF(0x1199, 0x9079, 10)}, /* Sierra Wireless EM74xx */ + {QMI_FIXED_INTF(0x1199, 0x907b, 8)}, /* Sierra Wireless EM74xx */ + {QMI_FIXED_INTF(0x1199, 0x907b, 10)}, /* Sierra Wireless EM74xx */ {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */ {QMI_FIXED_INTF(0x1bbb, 0x0203, 2)}, /* Alcatel L800MA */ {QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */ diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 25bc764ae7dc..d1c7029ded7c 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -2962,6 +2962,11 @@ vmxnet3_force_close(struct vmxnet3_adapter *adapter) /* we need to enable NAPI, otherwise dev_close will deadlock */ for (i = 0; i < adapter->num_rx_queues; i++) napi_enable(&adapter->rx_queue[i].napi); + /* + * Need to clear the quiesce bit to ensure that vmxnet3_close + * can quiesce the device properly + */ + clear_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state); dev_close(adapter->netdev); } diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index ceda5861da78..db882493875c 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -989,6 +989,7 @@ static u32 vrf_fib_table(const struct net_device *dev) static int vrf_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb) { + kfree_skb(skb); return 0; } @@ -998,7 +999,7 @@ static struct sk_buff *vrf_rcv_nfhook(u8 pf, unsigned int hook, { struct net *net = dev_net(dev); - if (NF_HOOK(pf, hook, net, NULL, skb, dev, NULL, vrf_rcv_finish) < 0) + if (nf_hook(pf, hook, net, NULL, skb, dev, NULL, vrf_rcv_finish) != 1) skb = NULL; /* kfree_skb(skb) handled by nf code */ return skb; diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 6ffc482550c1..7b61adb6270c 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1934,8 +1934,7 @@ abort_transaction_no_dev_fatal: xennet_disconnect_backend(info); xennet_destroy_queues(info); out: - unregister_netdev(info->netdev); - xennet_free_netdev(info->netdev); + device_unregister(&dev->dev); return err; } diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index 70e689bf1cad..dca7165fabcf 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c @@ -1754,6 +1754,10 @@ nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg) dev_info(ctrl->ctrl.device, "NVME-FC{%d}: resetting controller\n", ctrl->cnum); + /* stop the queues on error, cleanup is in reset thread */ + if (ctrl->queue_count > 1) + nvme_stop_queues(&ctrl->ctrl); + if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_RECONNECTING)) { dev_err(ctrl->ctrl.device, "NVME-FC{%d}: error_recovery: Couldn't change state " @@ -2720,6 +2724,12 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts, unsigned long flags; int ret, idx; + if (!(rport->remoteport.port_role & + (FC_PORT_ROLE_NVME_DISCOVERY | FC_PORT_ROLE_NVME_TARGET))) { + ret = -EBADR; + goto out_fail; + } + ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); if (!ctrl) { ret = -ENOMEM; diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index fed803232edc..4c2ff2bb26bc 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -1506,6 +1506,11 @@ static inline void nvme_release_cmb(struct nvme_dev *dev) if (dev->cmb) { iounmap(dev->cmb); dev->cmb = NULL; + if (dev->cmbsz) { + sysfs_remove_file_from_group(&dev->ctrl.device->kobj, + &dev_attr_cmb.attr, NULL); + dev->cmbsz = 0; + } } } @@ -1779,6 +1784,7 @@ static void nvme_pci_disable(struct nvme_dev *dev) { struct pci_dev *pdev = to_pci_dev(dev->dev); + nvme_release_cmb(dev); pci_free_irq_vectors(pdev); if (pci_is_enabled(pdev)) { @@ -2184,7 +2190,6 @@ static void nvme_remove(struct pci_dev *pdev) nvme_dev_disable(dev, true); nvme_dev_remove_admin(dev); nvme_free_queues(dev, 0); - nvme_release_cmb(dev); nvme_release_prp_pools(dev); nvme_dev_unmap(dev); nvme_put_ctrl(&dev->ctrl); diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c index cf90713043da..eb9399ac97cf 100644 --- a/drivers/nvme/target/core.c +++ b/drivers/nvme/target/core.c @@ -529,6 +529,12 @@ fail: } EXPORT_SYMBOL_GPL(nvmet_req_init); +void nvmet_req_uninit(struct nvmet_req *req) +{ + percpu_ref_put(&req->sq->ref); +} +EXPORT_SYMBOL_GPL(nvmet_req_uninit); + static inline bool nvmet_cc_en(u32 cc) { return cc & 0x1; diff --git a/drivers/nvme/target/fc.c b/drivers/nvme/target/fc.c index 62eba29c85fb..2006fae61980 100644 --- a/drivers/nvme/target/fc.c +++ b/drivers/nvme/target/fc.c @@ -517,9 +517,7 @@ nvmet_fc_queue_to_cpu(struct nvmet_fc_tgtport *tgtport, int qid) { int cpu, idx, cnt; - if (!(tgtport->ops->target_features & - NVMET_FCTGTFEAT_NEEDS_CMD_CPUSCHED) || - tgtport->ops->max_hw_queues == 1) + if (tgtport->ops->max_hw_queues == 1) return WORK_CPU_UNBOUND; /* Simple cpu selection based on qid modulo active cpu count */ diff --git a/drivers/nvme/target/fcloop.c b/drivers/nvme/target/fcloop.c index 15551ef79c8c..294a6611fb24 100644 --- a/drivers/nvme/target/fcloop.c +++ b/drivers/nvme/target/fcloop.c @@ -698,7 +698,6 @@ static struct nvmet_fc_target_template tgttemplate = { .dma_boundary = FCLOOP_DMABOUND_4G, /* optional features */ .target_features = NVMET_FCTGTFEAT_CMD_IN_ISR | - NVMET_FCTGTFEAT_NEEDS_CMD_CPUSCHED | NVMET_FCTGTFEAT_OPDONE_IN_ISR, /* sizes of additional private data for data structures */ .target_priv_sz = sizeof(struct fcloop_tport), diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h index 7cb77ba5993b..cfc5c7fb0ab7 100644 --- a/drivers/nvme/target/nvmet.h +++ b/drivers/nvme/target/nvmet.h @@ -261,6 +261,7 @@ u16 nvmet_parse_fabrics_cmd(struct nvmet_req *req); bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq, struct nvmet_sq *sq, struct nvmet_fabrics_ops *ops); +void nvmet_req_uninit(struct nvmet_req *req); void nvmet_req_complete(struct nvmet_req *req, u16 status); void nvmet_cq_setup(struct nvmet_ctrl *ctrl, struct nvmet_cq *cq, u16 qid, diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c index 99c69018a35f..9e45cde63376 100644 --- a/drivers/nvme/target/rdma.c +++ b/drivers/nvme/target/rdma.c @@ -567,6 +567,7 @@ static void nvmet_rdma_read_data_done(struct ib_cq *cq, struct ib_wc *wc) rsp->n_rdma = 0; if (unlikely(wc->status != IB_WC_SUCCESS)) { + nvmet_req_uninit(&rsp->req); nvmet_rdma_release_rsp(rsp); if (wc->status != IB_WC_WR_FLUSH_ERR) { pr_info("RDMA READ for CQE 0x%p failed with status %s (%d).\n", diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 3080d9dd031d..43bd69dceabf 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -507,6 +507,9 @@ void *__unflatten_device_tree(const void *blob, /* Allocate memory for the expanded device tree */ mem = dt_alloc(size + 4, __alignof__(struct device_node)); + if (!mem) + return NULL; + memset(mem, 0, size); *(__be32 *)(mem + size) = cpu_to_be32(0xdeadbeef); diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 4dec07ea510f..d507c3569a88 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -197,7 +197,7 @@ static int __init __reserved_mem_init_node(struct reserved_mem *rmem) const struct of_device_id *i; for (i = __reservedmem_of_table; i < &__rmem_of_table_sentinel; i++) { - int const (*initfn)(struct reserved_mem *rmem) = i->data; + reservedmem_of_init_fn initfn = i->data; const char *compat = i->compatible; if (!of_flat_dt_is_compatible(rmem->fdt_node, compat)) diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index e443b0d0b236..34b9ad6b3143 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -35,7 +35,7 @@ static struct bus_type ccwgroup_bus_type; static void __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev) { int i; - char str[8]; + char str[16]; for (i = 0; i < gdev->count; i++) { sprintf(str, "cdev%d", i); @@ -238,7 +238,7 @@ static void ccwgroup_release(struct device *dev) static int __ccwgroup_create_symlinks(struct ccwgroup_device *gdev) { - char str[8]; + char str[16]; int i, rc; for (i = 0; i < gdev->count; i++) { diff --git a/drivers/s390/cio/qdio_debug.h b/drivers/s390/cio/qdio_debug.h index f33ce8577619..1d595d17bf11 100644 --- a/drivers/s390/cio/qdio_debug.h +++ b/drivers/s390/cio/qdio_debug.h @@ -11,7 +11,7 @@ #include "qdio.h" /* that gives us 15 characters in the text event views */ -#define QDIO_DBF_LEN 16 +#define QDIO_DBF_LEN 32 extern debug_info_t *qdio_dbf_setup; extern debug_info_t *qdio_dbf_error; diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index f6aa21176d89..30bc6105aac3 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -701,6 +701,7 @@ enum qeth_discipline_id { }; struct qeth_discipline { + const struct device_type *devtype; void (*start_poll)(struct ccw_device *, int, unsigned long); qdio_handler_t *input_handler; qdio_handler_t *output_handler; @@ -875,6 +876,9 @@ extern struct qeth_discipline qeth_l2_discipline; extern struct qeth_discipline qeth_l3_discipline; extern const struct attribute_group *qeth_generic_attr_groups[]; extern const struct attribute_group *qeth_osn_attr_groups[]; +extern const struct attribute_group qeth_device_attr_group; +extern const struct attribute_group qeth_device_blkt_group; +extern const struct device_type qeth_generic_devtype; extern struct workqueue_struct *qeth_wq; int qeth_card_hw_is_reachable(struct qeth_card *); diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 38114a8d56e0..fc6d85f2b38d 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -5530,10 +5530,12 @@ void qeth_core_free_discipline(struct qeth_card *card) card->discipline = NULL; } -static const struct device_type qeth_generic_devtype = { +const struct device_type qeth_generic_devtype = { .name = "qeth_generic", .groups = qeth_generic_attr_groups, }; +EXPORT_SYMBOL_GPL(qeth_generic_devtype); + static const struct device_type qeth_osn_devtype = { .name = "qeth_osn", .groups = qeth_osn_attr_groups, @@ -5659,23 +5661,22 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev) goto err_card; } - if (card->info.type == QETH_CARD_TYPE_OSN) - gdev->dev.type = &qeth_osn_devtype; - else - gdev->dev.type = &qeth_generic_devtype; - switch (card->info.type) { case QETH_CARD_TYPE_OSN: case QETH_CARD_TYPE_OSM: rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2); if (rc) goto err_card; + + gdev->dev.type = (card->info.type != QETH_CARD_TYPE_OSN) + ? card->discipline->devtype + : &qeth_osn_devtype; rc = card->discipline->setup(card->gdev); if (rc) goto err_disc; - case QETH_CARD_TYPE_OSD: - case QETH_CARD_TYPE_OSX: + break; default: + gdev->dev.type = &qeth_generic_devtype; break; } @@ -5731,8 +5732,10 @@ static int qeth_core_set_online(struct ccwgroup_device *gdev) if (rc) goto err; rc = card->discipline->setup(card->gdev); - if (rc) + if (rc) { + qeth_core_free_discipline(card); goto err; + } } rc = card->discipline->set_online(gdev); err: diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index 75b29fd2fcf4..db6a285d41e0 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c @@ -413,12 +413,16 @@ static ssize_t qeth_dev_layer2_store(struct device *dev, if (card->options.layer2 == newdis) goto out; - else { - card->info.mac_bits = 0; - if (card->discipline) { - card->discipline->remove(card->gdev); - qeth_core_free_discipline(card); - } + if (card->info.type == QETH_CARD_TYPE_OSM) { + /* fixed layer, can't switch */ + rc = -EOPNOTSUPP; + goto out; + } + + card->info.mac_bits = 0; + if (card->discipline) { + card->discipline->remove(card->gdev); + qeth_core_free_discipline(card); } rc = qeth_core_load_discipline(card, newdis); @@ -426,6 +430,8 @@ static ssize_t qeth_dev_layer2_store(struct device *dev, goto out; rc = card->discipline->setup(card->gdev); + if (rc) + qeth_core_free_discipline(card); out: mutex_unlock(&card->discipline_mutex); return rc ? rc : count; @@ -703,10 +709,11 @@ static struct attribute *qeth_blkt_device_attrs[] = { &dev_attr_inter_jumbo.attr, NULL, }; -static struct attribute_group qeth_device_blkt_group = { +const struct attribute_group qeth_device_blkt_group = { .name = "blkt", .attrs = qeth_blkt_device_attrs, }; +EXPORT_SYMBOL_GPL(qeth_device_blkt_group); static struct attribute *qeth_device_attrs[] = { &dev_attr_state.attr, @@ -726,9 +733,10 @@ static struct attribute *qeth_device_attrs[] = { &dev_attr_switch_attrs.attr, NULL, }; -static struct attribute_group qeth_device_attr_group = { +const struct attribute_group qeth_device_attr_group = { .attrs = qeth_device_attrs, }; +EXPORT_SYMBOL_GPL(qeth_device_attr_group); const struct attribute_group *qeth_generic_attr_groups[] = { &qeth_device_attr_group, diff --git a/drivers/s390/net/qeth_l2.h b/drivers/s390/net/qeth_l2.h index 29d9fb3890ad..0d59f9a45ea9 100644 --- a/drivers/s390/net/qeth_l2.h +++ b/drivers/s390/net/qeth_l2.h @@ -8,6 +8,8 @@ #include "qeth_core.h" +extern const struct attribute_group *qeth_l2_attr_groups[]; + int qeth_l2_create_device_attributes(struct device *); void qeth_l2_remove_device_attributes(struct device *); void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card); diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 1b07f382d74c..bd2df62a5cdf 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -880,11 +880,21 @@ static int qeth_l2_stop(struct net_device *dev) return 0; } +static const struct device_type qeth_l2_devtype = { + .name = "qeth_layer2", + .groups = qeth_l2_attr_groups, +}; + static int qeth_l2_probe_device(struct ccwgroup_device *gdev) { struct qeth_card *card = dev_get_drvdata(&gdev->dev); + int rc; - qeth_l2_create_device_attributes(&gdev->dev); + if (gdev->dev.type == &qeth_generic_devtype) { + rc = qeth_l2_create_device_attributes(&gdev->dev); + if (rc) + return rc; + } INIT_LIST_HEAD(&card->vid_list); hash_init(card->mac_htable); card->options.layer2 = 1; @@ -896,7 +906,8 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev) { struct qeth_card *card = dev_get_drvdata(&cgdev->dev); - qeth_l2_remove_device_attributes(&cgdev->dev); + if (cgdev->dev.type == &qeth_generic_devtype) + qeth_l2_remove_device_attributes(&cgdev->dev); qeth_set_allowed_threads(card, 0, 1); wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); @@ -954,7 +965,6 @@ static int qeth_l2_setup_netdev(struct qeth_card *card) case QETH_CARD_TYPE_OSN: card->dev = alloc_netdev(0, "osn%d", NET_NAME_UNKNOWN, ether_setup); - card->dev->flags |= IFF_NOARP; break; default: card->dev = alloc_etherdev(0); @@ -969,9 +979,12 @@ static int qeth_l2_setup_netdev(struct qeth_card *card) card->dev->min_mtu = 64; card->dev->max_mtu = ETH_MAX_MTU; card->dev->netdev_ops = &qeth_l2_netdev_ops; - card->dev->ethtool_ops = - (card->info.type != QETH_CARD_TYPE_OSN) ? - &qeth_l2_ethtool_ops : &qeth_l2_osn_ops; + if (card->info.type == QETH_CARD_TYPE_OSN) { + card->dev->ethtool_ops = &qeth_l2_osn_ops; + card->dev->flags |= IFF_NOARP; + } else { + card->dev->ethtool_ops = &qeth_l2_ethtool_ops; + } card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; if (card->info.type == QETH_CARD_TYPE_OSD && !card->info.guestlan) { card->dev->hw_features = NETIF_F_SG; @@ -1269,6 +1282,7 @@ static int qeth_l2_control_event(struct qeth_card *card, } struct qeth_discipline qeth_l2_discipline = { + .devtype = &qeth_l2_devtype, .start_poll = qeth_qdio_start_poll, .input_handler = (qdio_handler_t *) qeth_qdio_input_handler, .output_handler = (qdio_handler_t *) qeth_qdio_output_handler, diff --git a/drivers/s390/net/qeth_l2_sys.c b/drivers/s390/net/qeth_l2_sys.c index 687972356d6b..9696baa49e2d 100644 --- a/drivers/s390/net/qeth_l2_sys.c +++ b/drivers/s390/net/qeth_l2_sys.c @@ -269,3 +269,11 @@ void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card) } else qeth_bridgeport_an_set(card, 0); } + +const struct attribute_group *qeth_l2_attr_groups[] = { + &qeth_device_attr_group, + &qeth_device_blkt_group, + /* l2 specific, see l2_{create,remove}_device_attributes(): */ + &qeth_l2_bridgeport_attr_group, + NULL, +}; diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 6e0354ef4b86..d8df1e635163 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -3039,8 +3039,13 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) static int qeth_l3_probe_device(struct ccwgroup_device *gdev) { struct qeth_card *card = dev_get_drvdata(&gdev->dev); + int rc; - qeth_l3_create_device_attributes(&gdev->dev); + rc = qeth_l3_create_device_attributes(&gdev->dev); + if (rc) + return rc; + hash_init(card->ip_htable); + hash_init(card->ip_mc_htable); card->options.layer2 = 0; card->info.hwtrap = 0; return 0; @@ -3306,6 +3311,7 @@ static int qeth_l3_control_event(struct qeth_card *card, } struct qeth_discipline qeth_l3_discipline = { + .devtype = &qeth_generic_devtype, .start_poll = qeth_qdio_start_poll, .input_handler = (qdio_handler_t *) qeth_qdio_input_handler, .output_handler = (qdio_handler_t *) qeth_qdio_output_handler, diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c index 2a76ea78a0bf..b18fe2014cf2 100644 --- a/drivers/s390/virtio/virtio_ccw.c +++ b/drivers/s390/virtio/virtio_ccw.c @@ -87,7 +87,7 @@ struct vq_info_block { } __packed; struct virtio_feature_desc { - __u32 features; + __le32 features; __u8 index; } __packed; diff --git a/drivers/scsi/cxlflash/Kconfig b/drivers/scsi/cxlflash/Kconfig index c052104e523e..a011c5dbf214 100644 --- a/drivers/scsi/cxlflash/Kconfig +++ b/drivers/scsi/cxlflash/Kconfig @@ -5,6 +5,7 @@ config CXLFLASH tristate "Support for IBM CAPI Flash" depends on PCI && SCSI && CXL && EEH + select IRQ_POLL default m help Allows CAPI Accelerated IO to Flash diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index a808e8ef1d08..234352da5c3c 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -407,11 +407,12 @@ unlock: * can_queue. Eventually we will hit the point where we run * on all reserved structs. */ -static void fc_fcp_can_queue_ramp_down(struct fc_lport *lport) +static bool fc_fcp_can_queue_ramp_down(struct fc_lport *lport) { struct fc_fcp_internal *si = fc_get_scsi_internal(lport); unsigned long flags; int can_queue; + bool changed = false; spin_lock_irqsave(lport->host->host_lock, flags); @@ -427,9 +428,11 @@ static void fc_fcp_can_queue_ramp_down(struct fc_lport *lport) if (!can_queue) can_queue = 1; lport->host->can_queue = can_queue; + changed = true; unlock: spin_unlock_irqrestore(lport->host->host_lock, flags); + return changed; } /* @@ -1896,11 +1899,11 @@ int fc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc_cmd) if (!fc_fcp_lport_queue_ready(lport)) { if (lport->qfull) { - fc_fcp_can_queue_ramp_down(lport); - shost_printk(KERN_ERR, lport->host, - "libfc: queue full, " - "reducing can_queue to %d.\n", - lport->host->can_queue); + if (fc_fcp_can_queue_ramp_down(lport)) + shost_printk(KERN_ERR, lport->host, + "libfc: queue full, " + "reducing can_queue to %d.\n", + lport->host->can_queue); } rc = SCSI_MLQUEUE_HOST_BUSY; goto out; diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 944b32ca4931..1c55408ac718 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -294,6 +294,7 @@ int lpfc_selective_reset(struct lpfc_hba *); void lpfc_reset_barrier(struct lpfc_hba *); int lpfc_sli_brdready(struct lpfc_hba *, uint32_t); int lpfc_sli_brdkill(struct lpfc_hba *); +int lpfc_sli_chipset_init(struct lpfc_hba *phba); int lpfc_sli_brdreset(struct lpfc_hba *); int lpfc_sli_brdrestart(struct lpfc_hba *); int lpfc_sli_hba_setup(struct lpfc_hba *); diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 1487406aea77..c7962dae4dab 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -630,7 +630,7 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint8_t fc4_type, NLP_EVT_DEVICE_RECOVERY); spin_lock_irq(shost->host_lock); ndlp->nlp_flag &= ~NLP_NVMET_RECOV; - spin_lock_irq(shost->host_lock); + spin_unlock_irq(shost->host_lock); } } diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 90ae354a9c45..4b1eb98c228d 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -3602,6 +3602,13 @@ lpfc_get_wwpn(struct lpfc_hba *phba) LPFC_MBOXQ_t *mboxq; MAILBOX_t *mb; + if (phba->sli_rev < LPFC_SLI_REV4) { + /* Reset the port first */ + lpfc_sli_brdrestart(phba); + rc = lpfc_sli_chipset_init(phba); + if (rc) + return (uint64_t)-1; + } mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); @@ -8847,7 +8854,7 @@ lpfc_sli4_queue_unset(struct lpfc_hba *phba) lpfc_wq_destroy(phba, phba->sli4_hba.nvmels_wq); /* Unset ELS work queue */ - if (phba->sli4_hba.els_cq) + if (phba->sli4_hba.els_wq) lpfc_wq_destroy(phba, phba->sli4_hba.els_wq); /* Unset unsolicited receive queue */ diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index 94434e621c33..0488580eea12 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -764,7 +764,6 @@ lpfc_nvmet_create_targetport(struct lpfc_hba *phba) lpfc_tgttemplate.max_sgl_segments = phba->cfg_nvme_seg_cnt + 1; lpfc_tgttemplate.max_hw_queues = phba->cfg_nvme_io_channel; lpfc_tgttemplate.target_features = NVMET_FCTGTFEAT_READDATA_RSP | - NVMET_FCTGTFEAT_NEEDS_CMD_CPUSCHED | NVMET_FCTGTFEAT_CMD_IN_ISR | NVMET_FCTGTFEAT_OPDONE_IN_ISR; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index cf19f4976f5f..2a4fc00dfa9b 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -4204,13 +4204,16 @@ lpfc_sli_brdreset(struct lpfc_hba *phba) /* Reset HBA */ lpfc_printf_log(phba, KERN_INFO, LOG_SLI, "0325 Reset HBA Data: x%x x%x\n", - phba->pport->port_state, psli->sli_flag); + (phba->pport) ? phba->pport->port_state : 0, + psli->sli_flag); /* perform board reset */ phba->fc_eventTag = 0; phba->link_events = 0; - phba->pport->fc_myDID = 0; - phba->pport->fc_prevDID = 0; + if (phba->pport) { + phba->pport->fc_myDID = 0; + phba->pport->fc_prevDID = 0; + } /* Turn off parity checking and serr during the physical reset */ pci_read_config_word(phba->pcidev, PCI_COMMAND, &cfg_value); @@ -4336,7 +4339,8 @@ lpfc_sli_brdrestart_s3(struct lpfc_hba *phba) /* Restart HBA */ lpfc_printf_log(phba, KERN_INFO, LOG_SLI, "0337 Restart HBA Data: x%x x%x\n", - phba->pport->port_state, psli->sli_flag); + (phba->pport) ? phba->pport->port_state : 0, + psli->sli_flag); word0 = 0; mb = (MAILBOX_t *) &word0; @@ -4350,7 +4354,7 @@ lpfc_sli_brdrestart_s3(struct lpfc_hba *phba) readl(to_slim); /* flush */ /* Only skip post after fc_ffinit is completed */ - if (phba->pport->port_state) + if (phba->pport && phba->pport->port_state) word0 = 1; /* This is really setting up word1 */ else word0 = 0; /* This is really setting up word1 */ @@ -4359,7 +4363,8 @@ lpfc_sli_brdrestart_s3(struct lpfc_hba *phba) readl(to_slim); /* flush */ lpfc_sli_brdreset(phba); - phba->pport->stopped = 0; + if (phba->pport) + phba->pport->stopped = 0; phba->link_state = LPFC_INIT_START; phba->hba_flag = 0; spin_unlock_irq(&phba->hbalock); @@ -4446,7 +4451,7 @@ lpfc_sli_brdrestart(struct lpfc_hba *phba) * iteration, the function will restart the HBA again. The function returns * zero if HBA successfully restarted else returns negative error code. **/ -static int +int lpfc_sli_chipset_init(struct lpfc_hba *phba) { uint32_t status, i = 0; diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index a4aadf5f4dc6..1cc814f1505a 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -3770,9 +3770,6 @@ static long pmcraid_ioctl_passthrough( pmcraid_err("couldn't build passthrough ioadls\n"); goto out_free_cmd; } - } else if (request_size < 0) { - rc = -EINVAL; - goto out_free_cmd; } /* If data is being written into the device, copy the data from user diff --git a/drivers/scsi/qedf/qedf.h b/drivers/scsi/qedf/qedf.h index 40aeb6bb96a2..07ee88200e91 100644 --- a/drivers/scsi/qedf/qedf.h +++ b/drivers/scsi/qedf/qedf.h @@ -259,7 +259,7 @@ struct qedf_io_log { uint16_t task_id; uint32_t port_id; /* Remote port fabric ID */ int lun; - char op; /* SCSI CDB */ + unsigned char op; /* SCSI CDB */ uint8_t lba[4]; unsigned int bufflen; /* SCSI buffer length */ unsigned int sg_count; /* Number of SG elements */ diff --git a/drivers/scsi/qedf/qedf_els.c b/drivers/scsi/qedf/qedf_els.c index c505d41f6dc8..90627033bde6 100644 --- a/drivers/scsi/qedf/qedf_els.c +++ b/drivers/scsi/qedf/qedf_els.c @@ -109,7 +109,7 @@ retry_els: did = fcport->rdata->ids.port_id; sid = fcport->sid; - __fc_fill_fc_hdr(fc_hdr, FC_RCTL_ELS_REQ, sid, did, + __fc_fill_fc_hdr(fc_hdr, FC_RCTL_ELS_REQ, did, sid, FC_TYPE_ELS, FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index cceddd995a4b..a5c97342fd5d 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -2895,7 +2895,7 @@ static int __qedf_probe(struct pci_dev *pdev, int mode) slowpath_params.drv_minor = QEDF_DRIVER_MINOR_VER; slowpath_params.drv_rev = QEDF_DRIVER_REV_VER; slowpath_params.drv_eng = QEDF_DRIVER_ENG_VER; - memcpy(slowpath_params.name, "qedf", QED_DRV_VER_STR_SIZE); + strncpy(slowpath_params.name, "qedf", QED_DRV_VER_STR_SIZE); rc = qed_ops->common->slowpath_start(qedf->cdev, &slowpath_params); if (rc) { QEDF_ERR(&(qedf->dbg_ctx), "Cannot start slowpath.\n"); diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 7bfbcfa7af40..61cdd99ae41e 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -763,6 +763,8 @@ struct scsi_device *__scsi_device_lookup(struct Scsi_Host *shost, struct scsi_device *sdev; list_for_each_entry(sdev, &shost->__devices, siblings) { + if (sdev->sdev_state == SDEV_DEL) + continue; if (sdev->channel == channel && sdev->id == id && sdev->lun ==lun) return sdev; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 814a4bd8405d..e31f1cc90b81 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -30,6 +30,7 @@ #include <scsi/scsi_driver.h> #include <scsi/scsi_eh.h> #include <scsi/scsi_host.h> +#include <scsi/scsi_transport.h> /* __scsi_init_queue() */ #include <scsi/scsi_dh.h> #include <trace/events/scsi.h> diff --git a/drivers/soc/bcm/brcmstb/common.c b/drivers/soc/bcm/brcmstb/common.c index b6195fdf0d00..22e98a90468c 100644 --- a/drivers/soc/bcm/brcmstb/common.c +++ b/drivers/soc/bcm/brcmstb/common.c @@ -49,7 +49,7 @@ static const struct of_device_id sun_top_ctrl_match[] = { { .compatible = "brcm,bcm7420-sun-top-ctrl", }, { .compatible = "brcm,bcm7425-sun-top-ctrl", }, { .compatible = "brcm,bcm7429-sun-top-ctrl", }, - { .compatible = "brcm,bcm7425-sun-top-ctrl", }, + { .compatible = "brcm,bcm7435-sun-top-ctrl", }, { .compatible = "brcm,brcmstb-sun-top-ctrl", }, { } }; diff --git a/drivers/soc/imx/Kconfig b/drivers/soc/imx/Kconfig index 357a5d8f8da0..a5b86a28f343 100644 --- a/drivers/soc/imx/Kconfig +++ b/drivers/soc/imx/Kconfig @@ -2,8 +2,9 @@ menu "i.MX SoC drivers" config IMX7_PM_DOMAINS bool "i.MX7 PM domains" - select PM_GENERIC_DOMAINS depends on SOC_IMX7D || (COMPILE_TEST && OF) + depends on PM + select PM_GENERIC_DOMAINS default y if SOC_IMX7D endmenu diff --git a/drivers/soc/ti/knav_dma.c b/drivers/soc/ti/knav_dma.c index ecebe2eecc3a..026182d3b27c 100644 --- a/drivers/soc/ti/knav_dma.c +++ b/drivers/soc/ti/knav_dma.c @@ -413,7 +413,7 @@ static int of_channel_match_helper(struct device_node *np, const char *name, * @name: slave channel name * @config: dma configuration parameters * - * Returns pointer to appropriate DMA channel on success or NULL. + * Returns pointer to appropriate DMA channel on success or error. */ void *knav_dma_open_channel(struct device *dev, const char *name, struct knav_dma_cfg *config) diff --git a/drivers/staging/android/ion/devicetree.txt b/drivers/staging/android/ion/devicetree.txt deleted file mode 100644 index 168715271f06..000000000000 --- a/drivers/staging/android/ion/devicetree.txt +++ /dev/null @@ -1,51 +0,0 @@ -Ion Memory Manager - -Ion is a memory manager that allows for sharing of buffers via dma-buf. -Ion allows for different types of allocation via an abstraction called -a 'heap'. A heap represents a specific type of memory. Each heap has -a different type. There can be multiple instances of the same heap -type. - -Specific heap instances are tied to heap IDs. Heap IDs are not to be specified -in the devicetree. - -Required properties for Ion - -- compatible: "linux,ion" PLUS a compatible property for the device - -All child nodes of a linux,ion node are interpreted as heaps - -required properties for heaps - -- compatible: compatible string for a heap type PLUS a compatible property -for the specific instance of the heap. Current heap types --- linux,ion-heap-system --- linux,ion-heap-system-contig --- linux,ion-heap-carveout --- linux,ion-heap-chunk --- linux,ion-heap-dma --- linux,ion-heap-custom - -Optional properties -- memory-region: A phandle to a memory region. Required for DMA heap type -(see reserved-memory.txt for details on the reservation) - -Example: - - ion { - compatbile = "hisilicon,ion", "linux,ion"; - - ion-system-heap { - compatbile = "hisilicon,system-heap", "linux,ion-heap-system" - }; - - ion-camera-region { - compatible = "hisilicon,camera-heap", "linux,ion-heap-dma" - memory-region = <&camera_region>; - }; - - ion-fb-region { - compatbile = "hisilicon,fb-heap", "linux,ion-heap-dma" - memory-region = <&fb_region>; - }; - } diff --git a/drivers/staging/ccree/ssi_request_mgr.c b/drivers/staging/ccree/ssi_request_mgr.c index 522bd62c102e..8611adf3bb2e 100644 --- a/drivers/staging/ccree/ssi_request_mgr.c +++ b/drivers/staging/ccree/ssi_request_mgr.c @@ -376,7 +376,6 @@ int send_request( rc = ssi_power_mgr_runtime_get(&drvdata->plat_dev->dev); if (rc != 0) { SSI_LOG_ERR("ssi_power_mgr_runtime_get returned %x\n",rc); - spin_unlock_bh(&req_mgr_h->hw_lock); return rc; } #endif diff --git a/drivers/staging/fsl-dpaa2/Kconfig b/drivers/staging/fsl-dpaa2/Kconfig index 2e325cb747ae..730fd6d4db33 100644 --- a/drivers/staging/fsl-dpaa2/Kconfig +++ b/drivers/staging/fsl-dpaa2/Kconfig @@ -12,6 +12,7 @@ config FSL_DPAA2 config FSL_DPAA2_ETH tristate "Freescale DPAA2 Ethernet" depends on FSL_DPAA2 && FSL_MC_DPIO + depends on NETDEVICES && ETHERNET ---help--- Ethernet driver for Freescale DPAA2 SoCs, using the Freescale MC bus driver diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c index 4723a0bd5067..1c6ed5b2a6f9 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c @@ -97,8 +97,9 @@ void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val) switch (variable) { case HW_VAR_BSSID: - rtl92e_writel(dev, BSSIDR, ((u32 *)(val))[0]); - rtl92e_writew(dev, BSSIDR+2, ((u16 *)(val+2))[0]); + /* BSSIDR 2 byte alignment */ + rtl92e_writew(dev, BSSIDR, *(u16 *)val); + rtl92e_writel(dev, BSSIDR + 2, *(u32 *)(val + 2)); break; case HW_VAR_MEDIA_STATUS: @@ -624,7 +625,7 @@ void rtl92e_get_eeprom_size(struct net_device *dev) struct r8192_priv *priv = rtllib_priv(dev); RT_TRACE(COMP_INIT, "===========>%s()\n", __func__); - curCR = rtl92e_readl(dev, EPROM_CMD); + curCR = rtl92e_readw(dev, EPROM_CMD); RT_TRACE(COMP_INIT, "read from Reg Cmd9346CR(%x):%x\n", EPROM_CMD, curCR); priv->epromtype = (curCR & EPROM_CMD_9356SEL) ? EEPROM_93C56 : @@ -961,8 +962,8 @@ static void _rtl92e_net_update(struct net_device *dev) rtl92e_config_rate(dev, &rate_config); priv->dot11CurrentPreambleMode = PREAMBLE_AUTO; priv->basic_rate = rate_config &= 0x15f; - rtl92e_writel(dev, BSSIDR, ((u32 *)net->bssid)[0]); - rtl92e_writew(dev, BSSIDR+4, ((u16 *)net->bssid)[2]); + rtl92e_writew(dev, BSSIDR, *(u16 *)net->bssid); + rtl92e_writel(dev, BSSIDR + 2, *(u32 *)(net->bssid + 2)); if (priv->rtllib->iw_mode == IW_MODE_ADHOC) { rtl92e_writew(dev, ATIMWND, 2); @@ -1182,8 +1183,7 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc, struct cb_desc *cb_desc, struct sk_buff *skb) { struct r8192_priv *priv = rtllib_priv(dev); - dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); + dma_addr_t mapping; struct tx_fwinfo_8190pci *pTxFwInfo; pTxFwInfo = (struct tx_fwinfo_8190pci *)skb->data; @@ -1194,8 +1194,6 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc, pTxFwInfo->Short = _rtl92e_query_is_short(pTxFwInfo->TxHT, pTxFwInfo->TxRate, cb_desc); - if (pci_dma_mapping_error(priv->pdev, mapping)) - netdev_err(dev, "%s(): DMA Mapping error\n", __func__); if (cb_desc->bAMPDUEnable) { pTxFwInfo->AllowAggregation = 1; pTxFwInfo->RxMF = cb_desc->ampdu_factor; @@ -1230,6 +1228,14 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc, } memset((u8 *)pdesc, 0, 12); + + mapping = pci_map_single(priv->pdev, skb->data, skb->len, + PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(priv->pdev, mapping)) { + netdev_err(dev, "%s(): DMA Mapping error\n", __func__); + return; + } + pdesc->LINIP = 0; pdesc->CmdInit = 1; pdesc->Offset = sizeof(struct tx_fwinfo_8190pci) + 8; diff --git a/drivers/staging/rtl8192e/rtl819x_TSProc.c b/drivers/staging/rtl8192e/rtl819x_TSProc.c index 48bbd9e8a52f..dcc4eb691889 100644 --- a/drivers/staging/rtl8192e/rtl819x_TSProc.c +++ b/drivers/staging/rtl8192e/rtl819x_TSProc.c @@ -306,11 +306,6 @@ static void MakeTSEntry(struct ts_common_info *pTsCommonInfo, u8 *Addr, pTsCommonInfo->TClasNum = TCLAS_Num; } -static bool IsACValid(unsigned int tid) -{ - return tid < 7; -} - bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS, u8 *Addr, u8 TID, enum tr_select TxRxSelect, bool bAddNewTs) { @@ -328,12 +323,6 @@ bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS, if (ieee->current_network.qos_data.supported == 0) { UP = 0; } else { - if (!IsACValid(TID)) { - netdev_warn(ieee->dev, "%s(): TID(%d) is not valid\n", - __func__, TID); - return false; - } - switch (TID) { case 0: case 3: @@ -351,6 +340,10 @@ bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS, case 7: UP = 7; break; + default: + netdev_warn(ieee->dev, "%s(): TID(%d) is not valid\n", + __func__, TID); + return false; } } diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c index 5e7a61f24f8d..36c3189fc4b7 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c @@ -3531,7 +3531,6 @@ int rtw_wdev_alloc(struct adapter *padapter, struct device *dev) pwdev_priv->power_mgmt = true; else pwdev_priv->power_mgmt = false; - kfree((u8 *)wdev); return ret; diff --git a/drivers/staging/typec/fusb302/fusb302.c b/drivers/staging/typec/fusb302/fusb302.c index 2cee9a952c9b..4a356e509fe4 100644 --- a/drivers/staging/typec/fusb302/fusb302.c +++ b/drivers/staging/typec/fusb302/fusb302.c @@ -264,22 +264,36 @@ static void fusb302_debugfs_exit(const struct fusb302_chip *chip) { } #define FUSB302_RESUME_RETRY 10 #define FUSB302_RESUME_RETRY_SLEEP 50 -static int fusb302_i2c_write(struct fusb302_chip *chip, - u8 address, u8 data) + +static bool fusb302_is_suspended(struct fusb302_chip *chip) { int retry_cnt; - int ret = 0; - atomic_set(&chip->i2c_busy, 1); for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) { if (atomic_read(&chip->pm_suspend)) { - pr_err("fusb302_i2c: pm suspend, retry %d/%d\n", - retry_cnt + 1, FUSB302_RESUME_RETRY); + dev_err(chip->dev, "i2c: pm suspend, retry %d/%d\n", + retry_cnt + 1, FUSB302_RESUME_RETRY); msleep(FUSB302_RESUME_RETRY_SLEEP); } else { - break; + return false; } } + + return true; +} + +static int fusb302_i2c_write(struct fusb302_chip *chip, + u8 address, u8 data) +{ + int ret = 0; + + atomic_set(&chip->i2c_busy, 1); + + if (fusb302_is_suspended(chip)) { + atomic_set(&chip->i2c_busy, 0); + return -ETIMEDOUT; + } + ret = i2c_smbus_write_byte_data(chip->i2c_client, address, data); if (ret < 0) fusb302_log(chip, "cannot write 0x%02x to 0x%02x, ret=%d", @@ -292,21 +306,17 @@ static int fusb302_i2c_write(struct fusb302_chip *chip, static int fusb302_i2c_block_write(struct fusb302_chip *chip, u8 address, u8 length, const u8 *data) { - int retry_cnt; int ret = 0; if (length <= 0) return ret; atomic_set(&chip->i2c_busy, 1); - for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) { - if (atomic_read(&chip->pm_suspend)) { - pr_err("fusb302_i2c: pm suspend, retry %d/%d\n", - retry_cnt + 1, FUSB302_RESUME_RETRY); - msleep(FUSB302_RESUME_RETRY_SLEEP); - } else { - break; - } + + if (fusb302_is_suspended(chip)) { + atomic_set(&chip->i2c_busy, 0); + return -ETIMEDOUT; } + ret = i2c_smbus_write_i2c_block_data(chip->i2c_client, address, length, data); if (ret < 0) @@ -320,19 +330,15 @@ static int fusb302_i2c_block_write(struct fusb302_chip *chip, u8 address, static int fusb302_i2c_read(struct fusb302_chip *chip, u8 address, u8 *data) { - int retry_cnt; int ret = 0; atomic_set(&chip->i2c_busy, 1); - for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) { - if (atomic_read(&chip->pm_suspend)) { - pr_err("fusb302_i2c: pm suspend, retry %d/%d\n", - retry_cnt + 1, FUSB302_RESUME_RETRY); - msleep(FUSB302_RESUME_RETRY_SLEEP); - } else { - break; - } + + if (fusb302_is_suspended(chip)) { + atomic_set(&chip->i2c_busy, 0); + return -ETIMEDOUT; } + ret = i2c_smbus_read_byte_data(chip->i2c_client, address); *data = (u8)ret; if (ret < 0) @@ -345,33 +351,31 @@ static int fusb302_i2c_read(struct fusb302_chip *chip, static int fusb302_i2c_block_read(struct fusb302_chip *chip, u8 address, u8 length, u8 *data) { - int retry_cnt; int ret = 0; if (length <= 0) return ret; atomic_set(&chip->i2c_busy, 1); - for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) { - if (atomic_read(&chip->pm_suspend)) { - pr_err("fusb302_i2c: pm suspend, retry %d/%d\n", - retry_cnt + 1, FUSB302_RESUME_RETRY); - msleep(FUSB302_RESUME_RETRY_SLEEP); - } else { - break; - } + + if (fusb302_is_suspended(chip)) { + atomic_set(&chip->i2c_busy, 0); + return -ETIMEDOUT; } + ret = i2c_smbus_read_i2c_block_data(chip->i2c_client, address, length, data); if (ret < 0) { fusb302_log(chip, "cannot block read 0x%02x, len=%d, ret=%d", address, length, ret); - return ret; + goto done; } if (ret != length) { fusb302_log(chip, "only read %d/%d bytes from 0x%02x", ret, length, address); - return -EIO; + ret = -EIO; } + +done: atomic_set(&chip->i2c_busy, 0); return ret; @@ -489,7 +493,7 @@ static int tcpm_init(struct tcpc_dev *dev) ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &data); if (ret < 0) return ret; - chip->vbus_present = !!(FUSB_REG_STATUS0 & FUSB_REG_STATUS0_VBUSOK); + chip->vbus_present = !!(data & FUSB_REG_STATUS0_VBUSOK); ret = fusb302_i2c_read(chip, FUSB_REG_DEVICE_ID, &data); if (ret < 0) return ret; @@ -1025,7 +1029,7 @@ static int fusb302_pd_send_message(struct fusb302_chip *chip, buf[pos++] = FUSB302_TKN_SYNC1; buf[pos++] = FUSB302_TKN_SYNC2; - len = pd_header_cnt(msg->header) * 4; + len = pd_header_cnt_le(msg->header) * 4; /* plug 2 for header */ len += 2; if (len > 0x1F) { @@ -1481,7 +1485,7 @@ static int fusb302_pd_read_message(struct fusb302_chip *chip, (u8 *)&msg->header); if (ret < 0) return ret; - len = pd_header_cnt(msg->header) * 4; + len = pd_header_cnt_le(msg->header) * 4; /* add 4 to length to include the CRC */ if (len > PD_MAX_PAYLOAD * 4) { fusb302_log(chip, "PD message too long %d", len); @@ -1663,14 +1667,12 @@ static int init_gpio(struct fusb302_chip *chip) if (ret < 0) { fusb302_log(chip, "cannot set GPIO Int_N to input, ret=%d", ret); - gpio_free(chip->gpio_int_n); return ret; } ret = gpio_to_irq(chip->gpio_int_n); if (ret < 0) { fusb302_log(chip, "cannot request IRQ for GPIO Int_N, ret=%d", ret); - gpio_free(chip->gpio_int_n); return ret; } chip->gpio_int_n_irq = ret; @@ -1787,11 +1789,13 @@ static const struct of_device_id fusb302_dt_match[] = { {.compatible = "fcs,fusb302"}, {}, }; +MODULE_DEVICE_TABLE(of, fusb302_dt_match); static const struct i2c_device_id fusb302_i2c_device_id[] = { {"typec_fusb302", 0}, {}, }; +MODULE_DEVICE_TABLE(i2c, fusb302_i2c_device_id); static const struct dev_pm_ops fusb302_pm_ops = { .suspend = fusb302_pm_suspend, diff --git a/drivers/staging/typec/pd.h b/drivers/staging/typec/pd.h index 8d97bdb95f23..510ef7279900 100644 --- a/drivers/staging/typec/pd.h +++ b/drivers/staging/typec/pd.h @@ -92,6 +92,16 @@ static inline unsigned int pd_header_type_le(__le16 header) return pd_header_type(le16_to_cpu(header)); } +static inline unsigned int pd_header_msgid(u16 header) +{ + return (header >> PD_HEADER_ID_SHIFT) & PD_HEADER_ID_MASK; +} + +static inline unsigned int pd_header_msgid_le(__le16 header) +{ + return pd_header_msgid(le16_to_cpu(header)); +} + #define PD_MAX_PAYLOAD 7 struct pd_message { diff --git a/drivers/staging/typec/pd_vdo.h b/drivers/staging/typec/pd_vdo.h index dba172e0e0d1..d92259f8de0a 100644 --- a/drivers/staging/typec/pd_vdo.h +++ b/drivers/staging/typec/pd_vdo.h @@ -22,6 +22,9 @@ * VDM object is minimum of VDM header + 6 additional data objects. */ +#define VDO_MAX_OBJECTS 6 +#define VDO_MAX_SIZE (VDO_MAX_OBJECTS + 1) + /* * VDM header * ---------- @@ -34,7 +37,6 @@ * <5> :: reserved (SVDM), command type (UVDM) * <4:0> :: command */ -#define VDO_MAX_SIZE 7 #define VDO(vid, type, custom) \ (((vid) << 16) | \ ((type) << 15) | \ diff --git a/drivers/staging/typec/tcpci.c b/drivers/staging/typec/tcpci.c index 5e5be74c7850..df72d8b01e73 100644 --- a/drivers/staging/typec/tcpci.c +++ b/drivers/staging/typec/tcpci.c @@ -425,7 +425,7 @@ static const struct regmap_config tcpci_regmap_config = { .max_register = 0x7F, /* 0x80 .. 0xFF are vendor defined */ }; -const struct tcpc_config tcpci_tcpc_config = { +static const struct tcpc_config tcpci_tcpc_config = { .type = TYPEC_PORT_DFP, .default_role = TYPEC_SINK, }; diff --git a/drivers/staging/typec/tcpm.c b/drivers/staging/typec/tcpm.c index abba655ba00a..20eb4ebcf8c3 100644 --- a/drivers/staging/typec/tcpm.c +++ b/drivers/staging/typec/tcpm.c @@ -238,6 +238,7 @@ struct tcpm_port { unsigned int hard_reset_count; bool pd_capable; bool explicit_contract; + unsigned int rx_msgid; /* Partner capabilities/requests */ u32 sink_request; @@ -251,6 +252,8 @@ struct tcpm_port { unsigned int nr_src_pdo; u32 snk_pdo[PDO_MAX_OBJECTS]; unsigned int nr_snk_pdo; + u32 snk_vdo[VDO_MAX_OBJECTS]; + unsigned int nr_snk_vdo; unsigned int max_snk_mv; unsigned int max_snk_ma; @@ -997,6 +1000,7 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt, struct pd_mode_data *modep; int rlen = 0; u16 svid; + int i; tcpm_log(port, "Rx VDM cmd 0x%x type %d cmd %d len %d", p0, cmd_type, cmd, cnt); @@ -1007,6 +1011,14 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt, case CMDT_INIT: switch (cmd) { case CMD_DISCOVER_IDENT: + /* 6.4.4.3.1: Only respond as UFP (device) */ + if (port->data_role == TYPEC_DEVICE && + port->nr_snk_vdo) { + for (i = 0; i < port->nr_snk_vdo; i++) + response[i + 1] + = cpu_to_le32(port->snk_vdo[i]); + rlen = port->nr_snk_vdo + 1; + } break; case CMD_DISCOVER_SVID: break; @@ -1415,6 +1427,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, break; case SOFT_RESET_SEND: port->message_id = 0; + port->rx_msgid = -1; if (port->pwr_role == TYPEC_SOURCE) next_state = SRC_SEND_CAPABILITIES; else @@ -1503,6 +1516,22 @@ static void tcpm_pd_rx_handler(struct work_struct *work) port->attached); if (port->attached) { + enum pd_ctrl_msg_type type = pd_header_type_le(msg->header); + unsigned int msgid = pd_header_msgid_le(msg->header); + + /* + * USB PD standard, 6.6.1.2: + * "... if MessageID value in a received Message is the + * same as the stored value, the receiver shall return a + * GoodCRC Message with that MessageID value and drop + * the Message (this is a retry of an already received + * Message). Note: this shall not apply to the Soft_Reset + * Message which always has a MessageID value of zero." + */ + if (msgid == port->rx_msgid && type != PD_CTRL_SOFT_RESET) + goto done; + port->rx_msgid = msgid; + /* * If both ends believe to be DFP/host, we have a data role * mismatch. @@ -1520,6 +1549,7 @@ static void tcpm_pd_rx_handler(struct work_struct *work) } } +done: mutex_unlock(&port->lock); kfree(event); } @@ -1719,8 +1749,7 @@ static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo) } ma = min(ma, port->max_snk_ma); - /* XXX: Any other flags need to be set? */ - flags = 0; + flags = RDO_USB_COMM | RDO_NO_SUSPEND; /* Set mismatch bit if offered power is less than operating power */ mw = ma * mv / 1000; @@ -1957,6 +1986,12 @@ static void tcpm_reset_port(struct tcpm_port *port) port->attached = false; port->pd_capable = false; + /* + * First Rx ID should be 0; set this to a sentinel of -1 so that + * we can check tcpm_pd_rx_handler() if we had seen it before. + */ + port->rx_msgid = -1; + port->tcpc->set_pd_rx(port->tcpc, false); tcpm_init_vbus(port); /* also disables charging */ tcpm_init_vconn(port); @@ -2170,6 +2205,7 @@ static void run_state_machine(struct tcpm_port *port) port->pwr_opmode = TYPEC_PWR_MODE_USB; port->caps_count = 0; port->message_id = 0; + port->rx_msgid = -1; port->explicit_contract = false; tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0); break; @@ -2329,6 +2365,7 @@ static void run_state_machine(struct tcpm_port *port) typec_set_pwr_opmode(port->typec_port, TYPEC_PWR_MODE_USB); port->pwr_opmode = TYPEC_PWR_MODE_USB; port->message_id = 0; + port->rx_msgid = -1; port->explicit_contract = false; tcpm_set_state(port, SNK_DISCOVERY, 0); break; @@ -2496,6 +2533,7 @@ static void run_state_machine(struct tcpm_port *port) /* Soft_Reset states */ case SOFT_RESET: port->message_id = 0; + port->rx_msgid = -1; tcpm_pd_send_control(port, PD_CTRL_ACCEPT); if (port->pwr_role == TYPEC_SOURCE) tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0); @@ -2504,6 +2542,7 @@ static void run_state_machine(struct tcpm_port *port) break; case SOFT_RESET_SEND: port->message_id = 0; + port->rx_msgid = -1; if (tcpm_pd_send_control(port, PD_CTRL_SOFT_RESET)) tcpm_set_state_cond(port, hard_reset_state(port), 0); else @@ -2568,6 +2607,14 @@ static void run_state_machine(struct tcpm_port *port) break; case PR_SWAP_SRC_SNK_SOURCE_OFF: tcpm_set_cc(port, TYPEC_CC_RD); + /* + * USB-PD standard, 6.2.1.4, Port Power Role: + * "During the Power Role Swap Sequence, for the initial Source + * Port, the Port Power Role field shall be set to Sink in the + * PS_RDY Message indicating that the initial Source’s power + * supply is turned off" + */ + tcpm_set_pwr_role(port, TYPEC_SINK); if (tcpm_pd_send_control(port, PD_CTRL_PS_RDY)) { tcpm_set_state(port, ERROR_RECOVERY, 0); break; @@ -2575,7 +2622,6 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_state_cond(port, SNK_UNATTACHED, PD_T_PS_SOURCE_ON); break; case PR_SWAP_SRC_SNK_SINK_ON: - tcpm_set_pwr_role(port, TYPEC_SINK); tcpm_swap_complete(port, 0); tcpm_set_state(port, SNK_STARTUP, 0); break; @@ -2587,8 +2633,15 @@ static void run_state_machine(struct tcpm_port *port) case PR_SWAP_SNK_SRC_SOURCE_ON: tcpm_set_cc(port, tcpm_rp_cc(port)); tcpm_set_vbus(port, true); - tcpm_pd_send_control(port, PD_CTRL_PS_RDY); + /* + * USB PD standard, 6.2.1.4: + * "Subsequent Messages initiated by the Policy Engine, + * such as the PS_RDY Message sent to indicate that Vbus + * is ready, will have the Port Power Role field set to + * Source." + */ tcpm_set_pwr_role(port, TYPEC_SOURCE); + tcpm_pd_send_control(port, PD_CTRL_PS_RDY); tcpm_swap_complete(port, 0); tcpm_set_state(port, SRC_STARTUP, 0); break; @@ -3292,6 +3345,20 @@ static int tcpm_copy_pdos(u32 *dest_pdo, const u32 *src_pdo, return nr_pdo; } +static int tcpm_copy_vdos(u32 *dest_vdo, const u32 *src_vdo, + unsigned int nr_vdo) +{ + unsigned int i; + + if (nr_vdo > VDO_MAX_OBJECTS) + nr_vdo = VDO_MAX_OBJECTS; + + for (i = 0; i < nr_vdo; i++) + dest_vdo[i] = src_vdo[i]; + + return nr_vdo; +} + void tcpm_update_source_capabilities(struct tcpm_port *port, const u32 *pdo, unsigned int nr_pdo) { @@ -3382,6 +3449,8 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) tcpc->config->nr_src_pdo); port->nr_snk_pdo = tcpm_copy_pdos(port->snk_pdo, tcpc->config->snk_pdo, tcpc->config->nr_snk_pdo); + port->nr_snk_vdo = tcpm_copy_vdos(port->snk_vdo, tcpc->config->snk_vdo, + tcpc->config->nr_snk_vdo); port->max_snk_mv = tcpc->config->max_snk_mv; port->max_snk_ma = tcpc->config->max_snk_ma; diff --git a/drivers/staging/typec/tcpm.h b/drivers/staging/typec/tcpm.h index 969b365e6549..19c307d31a5a 100644 --- a/drivers/staging/typec/tcpm.h +++ b/drivers/staging/typec/tcpm.h @@ -60,6 +60,9 @@ struct tcpc_config { const u32 *snk_pdo; unsigned int nr_snk_pdo; + const u32 *snk_vdo; + unsigned int nr_snk_vdo; + unsigned int max_snk_mv; unsigned int max_snk_ma; unsigned int max_snk_mw; diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c index 988ee61fb4a7..d04db3f55519 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c @@ -502,8 +502,15 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, */ sg_init_table(scatterlist, num_pages); /* Now set the pages for each scatterlist */ - for (i = 0; i < num_pages; i++) - sg_set_page(scatterlist + i, pages[i], PAGE_SIZE, 0); + for (i = 0; i < num_pages; i++) { + unsigned int len = PAGE_SIZE - offset; + + if (len > count) + len = count; + sg_set_page(scatterlist + i, pages[i], len, offset); + offset = 0; + count -= len; + } dma_buffers = dma_map_sg(g_dev, scatterlist, @@ -524,20 +531,20 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, u32 addr = sg_dma_address(sg); /* Note: addrs is the address + page_count - 1 - * The firmware expects the block to be page + * The firmware expects blocks after the first to be page- * aligned and a multiple of the page size */ WARN_ON(len == 0); - WARN_ON(len & ~PAGE_MASK); - WARN_ON(addr & ~PAGE_MASK); + WARN_ON(i && (i != (dma_buffers - 1)) && (len & ~PAGE_MASK)); + WARN_ON(i && (addr & ~PAGE_MASK)); if (k > 0 && - ((addrs[k - 1] & PAGE_MASK) | - ((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT) - == addr) { - addrs[k - 1] += (len >> PAGE_SHIFT); - } else { - addrs[k++] = addr | ((len >> PAGE_SHIFT) - 1); - } + ((addrs[k - 1] & PAGE_MASK) + + (((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT)) + == (addr & PAGE_MASK)) + addrs[k - 1] += ((len + PAGE_SIZE - 1) >> PAGE_SHIFT); + else + addrs[k++] = (addr & PAGE_MASK) | + (((len + PAGE_SIZE - 1) >> PAGE_SHIFT) - 1); } /* Partial cache lines (fragments) require special measures */ diff --git a/drivers/tee/Kconfig b/drivers/tee/Kconfig index 2330a4eb4e8b..a6df12d88f90 100644 --- a/drivers/tee/Kconfig +++ b/drivers/tee/Kconfig @@ -1,6 +1,7 @@ # Generic Trusted Execution Environment Configuration config TEE tristate "Trusted Execution Environment support" + depends on HAVE_ARM_SMCCC || COMPILE_TEST select DMA_SHARED_BUFFER select GENERIC_ALLOCATOR help diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index 1c196f87e9d9..ff04b7f8549f 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -279,7 +279,7 @@ static int uio_dev_add_attributes(struct uio_device *idev) map = kzalloc(sizeof(*map), GFP_KERNEL); if (!map) { ret = -ENOMEM; - goto err_map_kobj; + goto err_map; } kobject_init(&map->kobj, &map_attr_type); map->mem = mem; @@ -289,7 +289,7 @@ static int uio_dev_add_attributes(struct uio_device *idev) goto err_map_kobj; ret = kobject_uevent(&map->kobj, KOBJ_ADD); if (ret) - goto err_map; + goto err_map_kobj; } for (pi = 0; pi < MAX_UIO_PORT_REGIONS; pi++) { @@ -308,7 +308,7 @@ static int uio_dev_add_attributes(struct uio_device *idev) portio = kzalloc(sizeof(*portio), GFP_KERNEL); if (!portio) { ret = -ENOMEM; - goto err_portio_kobj; + goto err_portio; } kobject_init(&portio->kobj, &portio_attr_type); portio->port = port; @@ -319,7 +319,7 @@ static int uio_dev_add_attributes(struct uio_device *idev) goto err_portio_kobj; ret = kobject_uevent(&portio->kobj, KOBJ_ADD); if (ret) - goto err_portio; + goto err_portio_kobj; } return 0; diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index cfc3cff6e8d5..8e6ef671be9b 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -475,11 +475,11 @@ static void snoop_urb(struct usb_device *udev, if (userurb) { /* Async */ if (when == SUBMIT) - dev_info(&udev->dev, "userurb %p, ep%d %s-%s, " + dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, " "length %u\n", userurb, ep, t, d, length); else - dev_info(&udev->dev, "userurb %p, ep%d %s-%s, " + dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, " "actual_length %u status %d\n", userurb, ep, t, d, length, timeout_or_status); @@ -1895,7 +1895,7 @@ static int proc_reapurb(struct usb_dev_state *ps, void __user *arg) if (as) { int retval; - snoop(&ps->dev->dev, "reap %p\n", as->userurb); + snoop(&ps->dev->dev, "reap %pK\n", as->userurb); retval = processcompl(as, (void __user * __user *)arg); free_async(as); return retval; @@ -1912,7 +1912,7 @@ static int proc_reapurbnonblock(struct usb_dev_state *ps, void __user *arg) as = async_getcompleted(ps); if (as) { - snoop(&ps->dev->dev, "reap %p\n", as->userurb); + snoop(&ps->dev->dev, "reap %pK\n", as->userurb); retval = processcompl(as, (void __user * __user *)arg); free_async(as); } else { @@ -2043,7 +2043,7 @@ static int proc_reapurb_compat(struct usb_dev_state *ps, void __user *arg) if (as) { int retval; - snoop(&ps->dev->dev, "reap %p\n", as->userurb); + snoop(&ps->dev->dev, "reap %pK\n", as->userurb); retval = processcompl_compat(as, (void __user * __user *)arg); free_async(as); return retval; @@ -2060,7 +2060,7 @@ static int proc_reapurbnonblock_compat(struct usb_dev_state *ps, void __user *ar as = async_getcompleted(ps); if (as) { - snoop(&ps->dev->dev, "reap %p\n", as->userurb); + snoop(&ps->dev->dev, "reap %pK\n", as->userurb); retval = processcompl_compat(as, (void __user * __user *)arg); free_async(as); } else { @@ -2489,7 +2489,7 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, #endif case USBDEVFS_DISCARDURB: - snoop(&dev->dev, "%s: DISCARDURB %p\n", __func__, p); + snoop(&dev->dev, "%s: DISCARDURB %pK\n", __func__, p); ret = proc_unlinkurb(ps, p); break; diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 26d710eec7da..e72cbc751619 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1735,7 +1735,7 @@ int usb_hcd_unlink_urb (struct urb *urb, int status) if (retval == 0) retval = -EINPROGRESS; else if (retval != -EIDRM && retval != -EBUSY) - dev_dbg(&udev->dev, "hcd_unlink_urb %p fail %d\n", + dev_dbg(&udev->dev, "hcd_unlink_urb %pK fail %d\n", urb, retval); usb_put_dev(udev); } @@ -1902,7 +1902,7 @@ rescan: /* kick hcd */ unlink1(hcd, urb, -ESHUTDOWN); dev_dbg (hcd->self.controller, - "shutdown urb %p ep%d%s%s\n", + "shutdown urb %pK ep%d%s%s\n", urb, usb_endpoint_num(&ep->desc), is_in ? "in" : "out", ({ char *s; @@ -2532,6 +2532,7 @@ struct usb_hcd *__usb_create_hcd(const struct hc_driver *driver, hcd->bandwidth_mutex = kmalloc(sizeof(*hcd->bandwidth_mutex), GFP_KERNEL); if (!hcd->bandwidth_mutex) { + kfree(hcd->address0_mutex); kfree(hcd); dev_dbg(dev, "hcd bandwidth mutex alloc failed\n"); return NULL; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 9dca59ef18b3..b8bb20d7acdb 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -362,7 +362,8 @@ static void usb_set_lpm_parameters(struct usb_device *udev) } /* USB 2.0 spec Section 11.24.4.5 */ -static int get_hub_descriptor(struct usb_device *hdev, void *data) +static int get_hub_descriptor(struct usb_device *hdev, + struct usb_hub_descriptor *desc) { int i, ret, size; unsigned dtype; @@ -378,10 +379,18 @@ static int get_hub_descriptor(struct usb_device *hdev, void *data) for (i = 0; i < 3; i++) { ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB, - dtype << 8, 0, data, size, + dtype << 8, 0, desc, size, USB_CTRL_GET_TIMEOUT); - if (ret >= (USB_DT_HUB_NONVAR_SIZE + 2)) + if (hub_is_superspeed(hdev)) { + if (ret == size) + return ret; + } else if (ret >= USB_DT_HUB_NONVAR_SIZE + 2) { + /* Make sure we have the DeviceRemovable field. */ + size = USB_DT_HUB_NONVAR_SIZE + desc->bNbrPorts / 8 + 1; + if (ret < size) + return -EMSGSIZE; return ret; + } } return -EINVAL; } @@ -1313,7 +1322,7 @@ static int hub_configure(struct usb_hub *hub, } mutex_init(&hub->status_mutex); - hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL); + hub->descriptor = kzalloc(sizeof(*hub->descriptor), GFP_KERNEL); if (!hub->descriptor) { ret = -ENOMEM; goto fail; @@ -1321,13 +1330,19 @@ static int hub_configure(struct usb_hub *hub, /* Request the entire hub descriptor. * hub->descriptor can handle USB_MAXCHILDREN ports, - * but the hub can/will return fewer bytes here. + * but a (non-SS) hub can/will return fewer bytes here. */ ret = get_hub_descriptor(hdev, hub->descriptor); if (ret < 0) { message = "can't read hub descriptor"; goto fail; - } else if (hub->descriptor->bNbrPorts > USB_MAXCHILDREN) { + } + + maxchild = USB_MAXCHILDREN; + if (hub_is_superspeed(hdev)) + maxchild = min_t(unsigned, maxchild, USB_SS_MAXPORTS); + + if (hub->descriptor->bNbrPorts > maxchild) { message = "hub has too many ports!"; ret = -ENODEV; goto fail; diff --git a/drivers/usb/core/of.c b/drivers/usb/core/of.c index d787f195a9a6..d563cbcf76cf 100644 --- a/drivers/usb/core/of.c +++ b/drivers/usb/core/of.c @@ -53,6 +53,9 @@ EXPORT_SYMBOL_GPL(usb_of_get_child_node); * * Find the companion device from platform bus. * + * Takes a reference to the returned struct device which needs to be dropped + * after use. + * * Return: On success, a pointer to the companion device, %NULL on failure. */ struct device *usb_of_get_companion_dev(struct device *dev) diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index d75cb8c0f7df..47903d510955 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -338,7 +338,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) if (!urb || !urb->complete) return -EINVAL; if (urb->hcpriv) { - WARN_ONCE(1, "URB %p submitted while active\n", urb); + WARN_ONCE(1, "URB %pK submitted while active\n", urb); return -EBUSY; } diff --git a/drivers/usb/dwc3/dwc3-keystone.c b/drivers/usb/dwc3/dwc3-keystone.c index 72664700b8a2..12ee23f53cdd 100644 --- a/drivers/usb/dwc3/dwc3-keystone.c +++ b/drivers/usb/dwc3/dwc3-keystone.c @@ -107,6 +107,10 @@ static int kdwc3_probe(struct platform_device *pdev) return PTR_ERR(kdwc->usbss); kdwc->clk = devm_clk_get(kdwc->dev, "usb"); + if (IS_ERR(kdwc->clk)) { + dev_err(kdwc->dev, "unable to get usb clock\n"); + return PTR_ERR(kdwc->clk); + } error = clk_prepare_enable(kdwc->clk); if (error < 0) { diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index a15ec71d0423..84a2cebfc712 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -39,6 +39,8 @@ #define PCI_DEVICE_ID_INTEL_APL 0x5aaa #define PCI_DEVICE_ID_INTEL_KBP 0xa2b0 #define PCI_DEVICE_ID_INTEL_GLK 0x31aa +#define PCI_DEVICE_ID_INTEL_CNPLP 0x9dee +#define PCI_DEVICE_ID_INTEL_CNPH 0xa36e #define PCI_INTEL_BXT_DSM_UUID "732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511" #define PCI_INTEL_BXT_FUNC_PMU_PWR 4 @@ -270,6 +272,8 @@ static const struct pci_device_id dwc3_pci_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_APL), }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KBP), }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_GLK), }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CNPLP), }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CNPH), }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_NL_USB), }, { } /* Terminating Entry */ }; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 6f6f0b3be3ad..aea9a5b948b4 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1261,14 +1261,24 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) __dwc3_gadget_start_isoc(dwc, dep, cur_uf); dep->flags &= ~DWC3_EP_PENDING_REQUEST; } + return 0; } - return 0; + + if ((dep->flags & DWC3_EP_BUSY) && + !(dep->flags & DWC3_EP_MISSED_ISOC)) { + WARN_ON_ONCE(!dep->resource_index); + ret = __dwc3_gadget_kick_transfer(dep, + dep->resource_index); + } + + goto out; } if (!dwc3_calc_trbs_left(dep)) return 0; ret = __dwc3_gadget_kick_transfer(dep, 0); +out: if (ret == -EBUSY) ret = 0; @@ -3026,6 +3036,15 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt) return IRQ_HANDLED; } + /* + * With PCIe legacy interrupt, test shows that top-half irq handler can + * be called again after HW interrupt deassertion. Check if bottom-half + * irq event handler completes before caching new event to prevent + * losing events. + */ + if (evt->flags & DWC3_EVENT_PENDING) + return IRQ_HANDLED; + count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0)); count &= DWC3_GEVNTCOUNT_MASK; if (!count) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 71dd27c0d7f2..47dda3450abd 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -1858,12 +1858,12 @@ static int ffs_func_eps_enable(struct ffs_function *func) ep->ep->driver_data = ep; ep->ep->desc = ds; - comp_desc = (struct usb_ss_ep_comp_descriptor *)(ds + - USB_DT_ENDPOINT_SIZE); - ep->ep->maxburst = comp_desc->bMaxBurst + 1; - - if (needs_comp_desc) + if (needs_comp_desc) { + comp_desc = (struct usb_ss_ep_comp_descriptor *)(ds + + USB_DT_ENDPOINT_SIZE); + ep->ep->maxburst = comp_desc->bMaxBurst + 1; ep->ep->comp_desc = comp_desc; + } ret = usb_ep_enable(ep->ep); if (likely(!ret)) { diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c index 000677c991b0..9b0805f55ad7 100644 --- a/drivers/usb/gadget/function/u_serial.c +++ b/drivers/usb/gadget/function/u_serial.c @@ -1256,7 +1256,7 @@ static void gserial_console_exit(void) struct gscons_info *info = &gscons_info; unregister_console(&gserial_cons); - if (info->console_thread != NULL) + if (!IS_ERR_OR_NULL(info->console_thread)) kthread_stop(info->console_thread); gs_buf_free(&info->con_buf); } diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c index c79081952ea0..ccabb51cb98d 100644 --- a/drivers/usb/gadget/udc/dummy_hcd.c +++ b/drivers/usb/gadget/udc/dummy_hcd.c @@ -2008,7 +2008,7 @@ ss_hub_descriptor(struct usb_hub_descriptor *desc) HUB_CHAR_COMMON_OCPM); desc->bNbrPorts = 1; desc->u.ss.bHubHdrDecLat = 0x04; /* Worst case: 0.4 micro sec*/ - desc->u.ss.DeviceRemovable = 0xffff; + desc->u.ss.DeviceRemovable = 0; } static inline void hub_descriptor(struct usb_hub_descriptor *desc) @@ -2020,8 +2020,8 @@ static inline void hub_descriptor(struct usb_hub_descriptor *desc) HUB_CHAR_INDV_PORT_LPSM | HUB_CHAR_COMMON_OCPM); desc->bNbrPorts = 1; - desc->u.hs.DeviceRemovable[0] = 0xff; - desc->u.hs.DeviceRemovable[1] = 0xff; + desc->u.hs.DeviceRemovable[0] = 0; + desc->u.hs.DeviceRemovable[1] = 0xff; /* PortPwrCtrlMask */ } static int dummy_hub_control( diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index bc7b9be12f54..f1908ea9fbd8 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -384,8 +384,10 @@ static int ehci_platform_resume(struct device *dev) } companion_dev = usb_of_get_companion_dev(hcd->self.controller); - if (companion_dev) + if (companion_dev) { device_pm_wait_for_dev(hcd->self.controller, companion_dev); + put_device(companion_dev); + } ehci_resume(hcd, priv->reset_on_resume); return 0; diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index bfa7fa3d2eea..7bf78be1fd32 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -1269,7 +1269,7 @@ static void set_td_timer(struct r8a66597 *r8a66597, struct r8a66597_td *td) time = 30; break; default: - time = 300; + time = 50; break; } @@ -1785,6 +1785,7 @@ static void r8a66597_td_timer(unsigned long _r8a66597) pipe = td->pipe; pipe_stop(r8a66597, pipe); + /* Select a different address or endpoint */ new_td = td; do { list_move_tail(&new_td->queue, @@ -1794,7 +1795,8 @@ static void r8a66597_td_timer(unsigned long _r8a66597) new_td = td; break; } - } while (td != new_td && td->address == new_td->address); + } while (td != new_td && td->address == new_td->address && + td->pipe->info.epnum == new_td->pipe->info.epnum); start_transfer(r8a66597, new_td); diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 5e3e9d4c6956..0dde49c35dd2 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -419,7 +419,7 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) wait_for_completion(cmd->completion); if (cmd->status == COMP_COMMAND_ABORTED || - cmd->status == COMP_STOPPED) { + cmd->status == COMP_COMMAND_RING_STOPPED) { xhci_warn(xhci, "Timeout while waiting for stop endpoint command\n"); ret = -ETIME; } diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index bbe22bcc550a..1f1687e888d6 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -56,7 +56,7 @@ static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci, } if (max_packet) { - seg->bounce_buf = kzalloc(max_packet, flags | GFP_DMA); + seg->bounce_buf = kzalloc(max_packet, flags); if (!seg->bounce_buf) { dma_pool_free(xhci->segment_pool, seg->trbs, dma); kfree(seg); @@ -1724,7 +1724,7 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) xhci->dcbaa->dev_context_ptrs[0] = cpu_to_le64(xhci->scratchpad->sp_dma); for (i = 0; i < num_sp; i++) { dma_addr_t dma; - void *buf = dma_alloc_coherent(dev, xhci->page_size, &dma, + void *buf = dma_zalloc_coherent(dev, xhci->page_size, &dma, flags); if (!buf) goto fail_sp4; @@ -2307,10 +2307,11 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) /* Place limits on the number of roothub ports so that the hub * descriptors aren't longer than the USB core will allocate. */ - if (xhci->num_usb3_ports > 15) { + if (xhci->num_usb3_ports > USB_SS_MAXPORTS) { xhci_dbg_trace(xhci, trace_xhci_dbg_init, - "Limiting USB 3.0 roothub ports to 15."); - xhci->num_usb3_ports = 15; + "Limiting USB 3.0 roothub ports to %u.", + USB_SS_MAXPORTS); + xhci->num_usb3_ports = USB_SS_MAXPORTS; } if (xhci->num_usb2_ports > USB_MAXCHILDREN) { xhci_dbg_trace(xhci, trace_xhci_dbg_init, diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 7b86508ac8cf..fcf1f3f63e7a 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -52,6 +52,7 @@ #define PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI 0x0aa8 #define PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI 0x1aa8 #define PCI_DEVICE_ID_INTEL_APL_XHCI 0x5aa8 +#define PCI_DEVICE_ID_INTEL_DNV_XHCI 0x19d0 static const char hcd_name[] = "xhci_hcd"; @@ -166,7 +167,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI)) { + pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI)) { xhci->quirks |= XHCI_PME_STUCK_QUIRK; } if (pdev->vendor == PCI_VENDOR_ID_INTEL && @@ -175,7 +177,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) } if (pdev->vendor == PCI_VENDOR_ID_INTEL && (pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI)) + pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI)) xhci->quirks |= XHCI_MISSING_CAS; if (pdev->vendor == PCI_VENDOR_ID_ETRON && diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 7c2a9e7c8e0f..c04144b25a67 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -177,7 +177,7 @@ static int xhci_plat_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) - return -ENODEV; + return irq; /* * sysdev must point to a device that is known to the system firmware diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 74bf5c60a260..03f63f50afb6 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -323,7 +323,7 @@ static void xhci_handle_stopped_cmd_ring(struct xhci_hcd *xhci, if (i_cmd->status != COMP_COMMAND_ABORTED) continue; - i_cmd->status = COMP_STOPPED; + i_cmd->status = COMP_COMMAND_RING_STOPPED; xhci_dbg(xhci, "Turn aborted command %p to no-op\n", i_cmd->command_trb); @@ -641,8 +641,8 @@ static void xhci_giveback_urb_in_irq(struct xhci_hcd *xhci, xhci_urb_free_priv(urb_priv); usb_hcd_unlink_urb_from_ep(hcd, urb); spin_unlock(&xhci->lock); - usb_hcd_giveback_urb(hcd, urb, status); trace_xhci_urb_giveback(urb); + usb_hcd_giveback_urb(hcd, urb, status); spin_lock(&xhci->lock); } @@ -1380,7 +1380,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, cmd_comp_code = GET_COMP_CODE(le32_to_cpu(event->status)); /* If CMD ring stopped we own the trbs between enqueue and dequeue */ - if (cmd_comp_code == COMP_STOPPED) { + if (cmd_comp_code == COMP_COMMAND_RING_STOPPED) { complete_all(&xhci->cmd_ring_stop_completion); return; } @@ -1436,8 +1436,8 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, break; case TRB_CMD_NOOP: /* Is this an aborted command turned to NO-OP? */ - if (cmd->status == COMP_STOPPED) - cmd_comp_code = COMP_STOPPED; + if (cmd->status == COMP_COMMAND_RING_STOPPED) + cmd_comp_code = COMP_COMMAND_RING_STOPPED; break; case TRB_RESET_EP: WARN_ON(slot_id != TRB_TO_SLOT_ID( @@ -2677,11 +2677,12 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) struct xhci_hcd *xhci = hcd_to_xhci(hcd); union xhci_trb *event_ring_deq; irqreturn_t ret = IRQ_NONE; + unsigned long flags; dma_addr_t deq; u64 temp_64; u32 status; - spin_lock(&xhci->lock); + spin_lock_irqsave(&xhci->lock, flags); /* Check if the xHC generated the interrupt, or the irq is shared */ status = readl(&xhci->op_regs->status); if (status == ~(u32)0) { @@ -2707,12 +2708,9 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) */ status |= STS_EINT; writel(status, &xhci->op_regs->status); - /* FIXME when MSI-X is supported and there are multiple vectors */ - /* Clear the MSI-X event interrupt status */ - if (hcd->irq) { + if (!hcd->msi_enabled) { u32 irq_pending; - /* Acknowledge the PCI interrupt */ irq_pending = readl(&xhci->ir_set->irq_pending); irq_pending |= IMAN_IP; writel(irq_pending, &xhci->ir_set->irq_pending); @@ -2757,7 +2755,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) ret = IRQ_HANDLED; out: - spin_unlock(&xhci->lock); + spin_unlock_irqrestore(&xhci->lock, flags); return ret; } diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 2d1310220832..30f47d92a610 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -359,9 +359,10 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd) /* fall back to msi*/ ret = xhci_setup_msi(xhci); - if (!ret) - /* hcd->irq is 0, we have MSI */ + if (!ret) { + hcd->msi_enabled = 1; return 0; + } if (!pdev->irq) { xhci_err(xhci, "No msi-x/msi found and no IRQ in BIOS\n"); @@ -1763,7 +1764,7 @@ static int xhci_configure_endpoint_result(struct xhci_hcd *xhci, switch (*cmd_status) { case COMP_COMMAND_ABORTED: - case COMP_STOPPED: + case COMP_COMMAND_RING_STOPPED: xhci_warn(xhci, "Timeout while waiting for configure endpoint command\n"); ret = -ETIME; break; @@ -1813,7 +1814,7 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci, switch (*cmd_status) { case COMP_COMMAND_ABORTED: - case COMP_STOPPED: + case COMP_COMMAND_RING_STOPPED: xhci_warn(xhci, "Timeout while waiting for evaluate context command\n"); ret = -ETIME; break; @@ -3432,7 +3433,7 @@ static int xhci_discover_or_reset_device(struct usb_hcd *hcd, ret = reset_device_cmd->status; switch (ret) { case COMP_COMMAND_ABORTED: - case COMP_STOPPED: + case COMP_COMMAND_RING_STOPPED: xhci_warn(xhci, "Timeout waiting for reset device command\n"); ret = -ETIME; goto command_cleanup; @@ -3817,7 +3818,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, */ switch (command->status) { case COMP_COMMAND_ABORTED: - case COMP_STOPPED: + case COMP_COMMAND_RING_STOPPED: xhci_warn(xhci, "Timeout while waiting for setup device command\n"); ret = -ETIME; break; diff --git a/drivers/usb/misc/chaoskey.c b/drivers/usb/misc/chaoskey.c index e9cae4d82af2..15d4e64d3b65 100644 --- a/drivers/usb/misc/chaoskey.c +++ b/drivers/usb/misc/chaoskey.c @@ -192,7 +192,7 @@ static int chaoskey_probe(struct usb_interface *interface, dev->in_ep = in_ep; - if (udev->descriptor.idVendor != ALEA_VENDOR_ID) + if (le16_to_cpu(udev->descriptor.idVendor) != ALEA_VENDOR_ID) dev->reads_started = 1; dev->size = size; diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index 816afadc4707..7ca4c7e0ea0d 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -549,7 +549,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd, info.revision = le16_to_cpu(dev->udev->descriptor.bcdDevice); /* 0==UNKNOWN, 1==LOW(usb1.1) ,2=FULL(usb1.1), 3=HIGH(usb2.0) */ - info.speed = le16_to_cpu(dev->udev->speed); + info.speed = dev->udev->speed; info.if_num = dev->interface->cur_altsetting->desc.bInterfaceNumber; info.report_size = dev->report_size; diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index aa3c280fdf8d..0782ac6f5edf 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -926,6 +926,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device USB_MAJOR, dev->minor); exit: + kfree(get_version_reply); return retval; error: diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c index 3c6948af726a..f019d80ca9e4 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_con.c +++ b/drivers/usb/misc/sisusbvga/sisusb_con.c @@ -973,7 +973,7 @@ sisusbcon_set_origin(struct vc_data *c) mutex_unlock(&sisusb->lock); - return 1; + return true; } /* Interface routine */ diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index ac3a4952abb4..dbe617a735d8 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -2780,10 +2780,11 @@ int musb_host_setup(struct musb *musb, int power_budget) int ret; struct usb_hcd *hcd = musb->hcd; - MUSB_HST_MODE(musb); - musb->xceiv->otg->default_a = 1; - musb->xceiv->otg->state = OTG_STATE_A_IDLE; - + if (musb->port_mode == MUSB_PORT_MODE_HOST) { + MUSB_HST_MODE(musb); + musb->xceiv->otg->default_a = 1; + musb->xceiv->otg->state = OTG_STATE_A_IDLE; + } otg_set_host(musb->xceiv->otg, &hcd->self); hcd->self.otg_port = 1; musb->xceiv->otg->host = &hcd->self; diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c index 8b43c4b99f04..7870b37e0ea5 100644 --- a/drivers/usb/musb/tusb6010_omap.c +++ b/drivers/usb/musb/tusb6010_omap.c @@ -219,6 +219,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz, u32 dma_remaining; int src_burst, dst_burst; u16 csr; + u32 psize; int ch; s8 dmareq; s8 sync_dev; @@ -390,15 +391,19 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz, if (chdat->tx) { /* Send transfer_packet_sz packets at a time */ - musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, - chdat->transfer_packet_sz); + psize = musb_readl(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET); + psize &= ~0x7ff; + psize |= chdat->transfer_packet_sz; + musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, psize); musb_writel(ep_conf, TUSB_EP_TX_OFFSET, TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len)); } else { /* Receive transfer_packet_sz packets at a time */ - musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, - chdat->transfer_packet_sz << 16); + psize = musb_readl(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET); + psize &= ~(0x7ff << 16); + psize |= (chdat->transfer_packet_sz << 16); + musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, psize); musb_writel(ep_conf, TUSB_EP_RX_OFFSET, TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len)); diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index d38780fa8788..aba74f817dc6 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -809,10 +809,10 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) }, { USB_DEVICE(FTDI_VID, CYBER_CORTEX_AV_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, - { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID), - .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, - { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID), - .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID, 1) }, + { USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID, 1) }, + { USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_TINY_PID, 1) }, + { USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_TINY_H_PID, 1) }, { USB_DEVICE(FIC_VID, FIC_NEO1973_DEBUG_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(FTDI_VID, FTDI_OOCDLINK_PID), @@ -1527,9 +1527,9 @@ static int set_serial_info(struct tty_struct *tty, (new_serial.flags & ASYNC_FLAGS)); priv->custom_divisor = new_serial.custom_divisor; +check_and_exit: write_latency_timer(port); -check_and_exit: if ((old_priv.flags & ASYNC_SPD_MASK) != (priv->flags & ASYNC_SPD_MASK)) { if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 71fb9e59db71..4fcf1cecb6d7 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -882,6 +882,8 @@ /* Olimex */ #define OLIMEX_VID 0x15BA #define OLIMEX_ARM_USB_OCD_PID 0x0003 +#define OLIMEX_ARM_USB_TINY_PID 0x0004 +#define OLIMEX_ARM_USB_TINY_H_PID 0x002a #define OLIMEX_ARM_USB_OCD_H_PID 0x002b /* diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 87798e625d6c..6cefb9cb133d 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -2336,8 +2336,11 @@ static void change_port_settings(struct tty_struct *tty, if (!baud) { /* pick a default, any default... */ baud = 9600; - } else + } else { + /* Avoid a zero divisor. */ + baud = min(baud, 461550); tty_encode_baud_rate(tty, baud, baud); + } edge_port->baud_rate = baud; config->wBaudRate = (__u16)((461550L + baud/2) / baud); diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 73956d48a0c5..f9734a96d516 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -197,6 +197,7 @@ static u8 ir_xbof_change(u8 xbof) static int ir_startup(struct usb_serial *serial) { struct usb_irda_cs_descriptor *irda_desc; + int rates; irda_desc = irda_usb_find_class_desc(serial, 0); if (!irda_desc) { @@ -205,18 +206,20 @@ static int ir_startup(struct usb_serial *serial) return -ENODEV; } + rates = le16_to_cpu(irda_desc->wBaudRate); + dev_dbg(&serial->dev->dev, "%s - Baud rates supported:%s%s%s%s%s%s%s%s%s\n", __func__, - (irda_desc->wBaudRate & USB_IRDA_BR_2400) ? " 2400" : "", - (irda_desc->wBaudRate & USB_IRDA_BR_9600) ? " 9600" : "", - (irda_desc->wBaudRate & USB_IRDA_BR_19200) ? " 19200" : "", - (irda_desc->wBaudRate & USB_IRDA_BR_38400) ? " 38400" : "", - (irda_desc->wBaudRate & USB_IRDA_BR_57600) ? " 57600" : "", - (irda_desc->wBaudRate & USB_IRDA_BR_115200) ? " 115200" : "", - (irda_desc->wBaudRate & USB_IRDA_BR_576000) ? " 576000" : "", - (irda_desc->wBaudRate & USB_IRDA_BR_1152000) ? " 1152000" : "", - (irda_desc->wBaudRate & USB_IRDA_BR_4000000) ? " 4000000" : ""); + (rates & USB_IRDA_BR_2400) ? " 2400" : "", + (rates & USB_IRDA_BR_9600) ? " 9600" : "", + (rates & USB_IRDA_BR_19200) ? " 19200" : "", + (rates & USB_IRDA_BR_38400) ? " 38400" : "", + (rates & USB_IRDA_BR_57600) ? " 57600" : "", + (rates & USB_IRDA_BR_115200) ? " 115200" : "", + (rates & USB_IRDA_BR_576000) ? " 576000" : "", + (rates & USB_IRDA_BR_1152000) ? " 1152000" : "", + (rates & USB_IRDA_BR_4000000) ? " 4000000" : ""); switch (irda_desc->bmAdditionalBOFs) { case USB_IRDA_AB_48: diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index edbc81f205c2..70f346f1aa86 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -189,7 +189,7 @@ static int mct_u232_set_baud_rate(struct tty_struct *tty, return -ENOMEM; divisor = mct_u232_calculate_baud_rate(serial, value, &speed); - put_unaligned_le32(cpu_to_le32(divisor), buf); + put_unaligned_le32(divisor, buf); rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), MCT_U232_SET_BAUD_RATE_REQUEST, MCT_U232_SET_REQUEST_TYPE, diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index af67a0de6b5d..3bf61acfc26b 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -281,6 +281,7 @@ static void option_instat_callback(struct urb *urb); #define TELIT_PRODUCT_LE922_USBCFG0 0x1042 #define TELIT_PRODUCT_LE922_USBCFG3 0x1043 #define TELIT_PRODUCT_LE922_USBCFG5 0x1045 +#define TELIT_PRODUCT_ME910 0x1100 #define TELIT_PRODUCT_LE920 0x1200 #define TELIT_PRODUCT_LE910 0x1201 #define TELIT_PRODUCT_LE910_USBCFG4 0x1206 @@ -640,6 +641,11 @@ static const struct option_blacklist_info simcom_sim7100e_blacklist = { .reserved = BIT(5) | BIT(6), }; +static const struct option_blacklist_info telit_me910_blacklist = { + .sendsetup = BIT(0), + .reserved = BIT(1) | BIT(3), +}; + static const struct option_blacklist_info telit_le910_blacklist = { .sendsetup = BIT(0), .reserved = BIT(1) | BIT(2), @@ -1235,6 +1241,8 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG5, 0xff), .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910), + .driver_info = (kernel_ulong_t)&telit_me910_blacklist }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910), .driver_info = (kernel_ulong_t)&telit_le910_blacklist }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910_USBCFG4), diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 38b3f0d8cd58..fd509ed6cf70 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -162,6 +162,8 @@ static const struct usb_device_id id_table[] = { {DEVICE_SWI(0x1199, 0x9071)}, /* Sierra Wireless MC74xx */ {DEVICE_SWI(0x1199, 0x9078)}, /* Sierra Wireless EM74xx */ {DEVICE_SWI(0x1199, 0x9079)}, /* Sierra Wireless EM74xx */ + {DEVICE_SWI(0x1199, 0x907a)}, /* Sierra Wireless EM74xx QDL */ + {DEVICE_SWI(0x1199, 0x907b)}, /* Sierra Wireless EM74xx */ {DEVICE_SWI(0x413c, 0x81a2)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */ {DEVICE_SWI(0x413c, 0x81a3)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */ {DEVICE_SWI(0x413c, 0x81a4)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */ diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c index 22b850a1ce06..28100374f7bd 100644 --- a/drivers/usb/storage/ene_ub6250.c +++ b/drivers/usb/storage/ene_ub6250.c @@ -446,6 +446,10 @@ struct ms_lib_ctrl { #define SD_BLOCK_LEN 9 struct ene_ub6250_info { + + /* I/O bounce buffer */ + u8 *bbuf; + /* for 6250 code */ struct SD_STATUS SD_Status; struct MS_STATUS MS_Status; @@ -493,8 +497,11 @@ static int ene_load_bincode(struct us_data *us, unsigned char flag); static void ene_ub6250_info_destructor(void *extra) { + struct ene_ub6250_info *info = (struct ene_ub6250_info *) extra; + if (!extra) return; + kfree(info->bbuf); } static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg) @@ -876,8 +883,9 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr, u8 PageNum, u32 *PageBuf, struct ms_lib_type_extdat *ExtraDat) { struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; + struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; + u8 *bbuf = info->bbuf; int result; - u8 ExtBuf[4]; u32 bn = PhyBlockAddr * 0x20 + PageNum; result = ene_load_bincode(us, MS_RW_PATTERN); @@ -917,7 +925,7 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr, bcb->CDB[2] = (unsigned char)(PhyBlockAddr>>16); bcb->CDB[6] = 0x01; - result = ene_send_scsi_cmd(us, FDIR_READ, &ExtBuf, 0); + result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -926,9 +934,9 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr, ExtraDat->status0 = 0x10; /* Not yet,fireware support */ ExtraDat->status1 = 0x00; /* Not yet,fireware support */ - ExtraDat->ovrflg = ExtBuf[0]; - ExtraDat->mngflg = ExtBuf[1]; - ExtraDat->logadr = memstick_logaddr(ExtBuf[2], ExtBuf[3]); + ExtraDat->ovrflg = bbuf[0]; + ExtraDat->mngflg = bbuf[1]; + ExtraDat->logadr = memstick_logaddr(bbuf[2], bbuf[3]); return USB_STOR_TRANSPORT_GOOD; } @@ -1348,8 +1356,9 @@ static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock, u8 PageNum, struct ms_lib_type_extdat *ExtraDat) { struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; + struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; + u8 *bbuf = info->bbuf; int result; - u8 ExtBuf[4]; memset(bcb, 0, sizeof(struct bulk_cb_wrap)); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); @@ -1363,7 +1372,7 @@ static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock, bcb->CDB[2] = (unsigned char)(PhyBlock>>16); bcb->CDB[6] = 0x01; - result = ene_send_scsi_cmd(us, FDIR_READ, &ExtBuf, 0); + result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -1371,9 +1380,9 @@ static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock, ExtraDat->intr = 0x80; /* Not yet, waiting for fireware support */ ExtraDat->status0 = 0x10; /* Not yet, waiting for fireware support */ ExtraDat->status1 = 0x00; /* Not yet, waiting for fireware support */ - ExtraDat->ovrflg = ExtBuf[0]; - ExtraDat->mngflg = ExtBuf[1]; - ExtraDat->logadr = memstick_logaddr(ExtBuf[2], ExtBuf[3]); + ExtraDat->ovrflg = bbuf[0]; + ExtraDat->mngflg = bbuf[1]; + ExtraDat->logadr = memstick_logaddr(bbuf[2], bbuf[3]); return USB_STOR_TRANSPORT_GOOD; } @@ -1559,9 +1568,9 @@ static int ms_lib_scan_logicalblocknumber(struct us_data *us, u16 btBlk1st) u16 PhyBlock, newblk, i; u16 LogStart, LogEnde; struct ms_lib_type_extdat extdat; - u8 buf[0x200]; u32 count = 0, index = 0; struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; + u8 *bbuf = info->bbuf; for (PhyBlock = 0; PhyBlock < info->MS_Lib.NumberOfPhyBlock;) { ms_lib_phy_to_log_range(PhyBlock, &LogStart, &LogEnde); @@ -1575,14 +1584,16 @@ static int ms_lib_scan_logicalblocknumber(struct us_data *us, u16 btBlk1st) } if (count == PhyBlock) { - ms_lib_read_extrablock(us, PhyBlock, 0, 0x80, &buf); + ms_lib_read_extrablock(us, PhyBlock, 0, 0x80, + bbuf); count += 0x80; } index = (PhyBlock % 0x80) * 4; - extdat.ovrflg = buf[index]; - extdat.mngflg = buf[index+1]; - extdat.logadr = memstick_logaddr(buf[index+2], buf[index+3]); + extdat.ovrflg = bbuf[index]; + extdat.mngflg = bbuf[index+1]; + extdat.logadr = memstick_logaddr(bbuf[index+2], + bbuf[index+3]); if ((extdat.ovrflg & MS_REG_OVR_BKST) != MS_REG_OVR_BKST_OK) { ms_lib_setacquired_errorblock(us, PhyBlock); @@ -2067,9 +2078,9 @@ static int ene_ms_init(struct us_data *us) { struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; int result; - u8 buf[0x200]; u16 MSP_BlockSize, MSP_UserAreaBlocks; struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; + u8 *bbuf = info->bbuf; printk(KERN_INFO "transport --- ENE_MSInit\n"); @@ -2088,13 +2099,13 @@ static int ene_ms_init(struct us_data *us) bcb->CDB[0] = 0xF1; bcb->CDB[1] = 0x01; - result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0); + result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0); if (result != USB_STOR_XFER_GOOD) { printk(KERN_ERR "Execution MS Init Code Fail !!\n"); return USB_STOR_TRANSPORT_ERROR; } /* the same part to test ENE */ - info->MS_Status = *(struct MS_STATUS *)&buf[0]; + info->MS_Status = *(struct MS_STATUS *) bbuf; if (info->MS_Status.Insert && info->MS_Status.Ready) { printk(KERN_INFO "Insert = %x\n", info->MS_Status.Insert); @@ -2103,15 +2114,15 @@ static int ene_ms_init(struct us_data *us) printk(KERN_INFO "IsMSPHG = %x\n", info->MS_Status.IsMSPHG); printk(KERN_INFO "WtP= %x\n", info->MS_Status.WtP); if (info->MS_Status.IsMSPro) { - MSP_BlockSize = (buf[6] << 8) | buf[7]; - MSP_UserAreaBlocks = (buf[10] << 8) | buf[11]; + MSP_BlockSize = (bbuf[6] << 8) | bbuf[7]; + MSP_UserAreaBlocks = (bbuf[10] << 8) | bbuf[11]; info->MSP_TotalBlock = MSP_BlockSize * MSP_UserAreaBlocks; } else { ms_card_init(us); /* Card is MS (to ms.c)*/ } usb_stor_dbg(us, "MS Init Code OK !!\n"); } else { - usb_stor_dbg(us, "MS Card Not Ready --- %x\n", buf[0]); + usb_stor_dbg(us, "MS Card Not Ready --- %x\n", bbuf[0]); return USB_STOR_TRANSPORT_ERROR; } @@ -2121,9 +2132,9 @@ static int ene_ms_init(struct us_data *us) static int ene_sd_init(struct us_data *us) { int result; - u8 buf[0x200]; struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; + u8 *bbuf = info->bbuf; usb_stor_dbg(us, "transport --- ENE_SDInit\n"); /* SD Init Part-1 */ @@ -2157,17 +2168,17 @@ static int ene_sd_init(struct us_data *us) bcb->Flags = US_BULK_FLAG_IN; bcb->CDB[0] = 0xF1; - result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0); + result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0); if (result != USB_STOR_XFER_GOOD) { usb_stor_dbg(us, "Execution SD Init Code Fail !!\n"); return USB_STOR_TRANSPORT_ERROR; } - info->SD_Status = *(struct SD_STATUS *)&buf[0]; + info->SD_Status = *(struct SD_STATUS *) bbuf; if (info->SD_Status.Insert && info->SD_Status.Ready) { struct SD_STATUS *s = &info->SD_Status; - ene_get_card_status(us, (unsigned char *)&buf); + ene_get_card_status(us, bbuf); usb_stor_dbg(us, "Insert = %x\n", s->Insert); usb_stor_dbg(us, "Ready = %x\n", s->Ready); usb_stor_dbg(us, "IsMMC = %x\n", s->IsMMC); @@ -2175,7 +2186,7 @@ static int ene_sd_init(struct us_data *us) usb_stor_dbg(us, "HiSpeed = %x\n", s->HiSpeed); usb_stor_dbg(us, "WtP = %x\n", s->WtP); } else { - usb_stor_dbg(us, "SD Card Not Ready --- %x\n", buf[0]); + usb_stor_dbg(us, "SD Card Not Ready --- %x\n", bbuf[0]); return USB_STOR_TRANSPORT_ERROR; } return USB_STOR_TRANSPORT_GOOD; @@ -2185,13 +2196,15 @@ static int ene_sd_init(struct us_data *us) static int ene_init(struct us_data *us) { int result; - u8 misc_reg03 = 0; + u8 misc_reg03; struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); + u8 *bbuf = info->bbuf; - result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03); + result = ene_get_card_type(us, REG_CARD_STATUS, bbuf); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; + misc_reg03 = bbuf[0]; if (misc_reg03 & 0x01) { if (!info->SD_Status.Ready) { result = ene_sd_init(us); @@ -2318,8 +2331,9 @@ static int ene_ub6250_probe(struct usb_interface *intf, const struct usb_device_id *id) { int result; - u8 misc_reg03 = 0; + u8 misc_reg03; struct us_data *us; + struct ene_ub6250_info *info; result = usb_stor_probe1(&us, intf, id, (id - ene_ub6250_usb_ids) + ene_ub6250_unusual_dev_list, @@ -2328,11 +2342,16 @@ static int ene_ub6250_probe(struct usb_interface *intf, return result; /* FIXME: where should the code alloc extra buf ? */ - if (!us->extra) { - us->extra = kzalloc(sizeof(struct ene_ub6250_info), GFP_KERNEL); - if (!us->extra) - return -ENOMEM; - us->extra_destructor = ene_ub6250_info_destructor; + us->extra = kzalloc(sizeof(struct ene_ub6250_info), GFP_KERNEL); + if (!us->extra) + return -ENOMEM; + us->extra_destructor = ene_ub6250_info_destructor; + + info = (struct ene_ub6250_info *)(us->extra); + info->bbuf = kmalloc(512, GFP_KERNEL); + if (!info->bbuf) { + kfree(us->extra); + return -ENOMEM; } us->transport_name = "ene_ub6250"; @@ -2344,12 +2363,13 @@ static int ene_ub6250_probe(struct usb_interface *intf, return result; /* probe card type */ - result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03); + result = ene_get_card_type(us, REG_CARD_STATUS, info->bbuf); if (result != USB_STOR_XFER_GOOD) { usb_stor_disconnect(intf); return USB_STOR_TRANSPORT_ERROR; } + misc_reg03 = info->bbuf[0]; if (!(misc_reg03 & 0x01)) { pr_info("ums_eneub6250: This driver only supports SD/MS cards. " "It does not support SM cards.\n"); diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c index 5d8b2c261940..0585078638db 100644 --- a/drivers/usb/usbip/vhci_hcd.c +++ b/drivers/usb/usbip/vhci_hcd.c @@ -235,14 +235,19 @@ done: static inline void hub_descriptor(struct usb_hub_descriptor *desc) { + int width; + memset(desc, 0, sizeof(*desc)); desc->bDescriptorType = USB_DT_HUB; - desc->bDescLength = 9; desc->wHubCharacteristics = cpu_to_le16( HUB_CHAR_INDV_PORT_LPSM | HUB_CHAR_COMMON_OCPM); + desc->bNbrPorts = VHCI_HC_PORTS; - desc->u.hs.DeviceRemovable[0] = 0xff; - desc->u.hs.DeviceRemovable[1] = 0xff; + BUILD_BUG_ON(VHCI_HC_PORTS > USB_MAXCHILDREN); + width = desc->bNbrPorts / 8 + 1; + desc->bDescLength = USB_DT_HUB_NONVAR_SIZE + 2 * width; + memset(&desc->u.hs.DeviceRemovable[0], 0, width); + memset(&desc->u.hs.DeviceRemovable[width], 0xff, width); } static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, diff --git a/drivers/uwb/i1480/dfu/usb.c b/drivers/uwb/i1480/dfu/usb.c index 6345e85822a4..a50cf45e530f 100644 --- a/drivers/uwb/i1480/dfu/usb.c +++ b/drivers/uwb/i1480/dfu/usb.c @@ -341,6 +341,7 @@ error_submit_ep1: static int i1480_usb_probe(struct usb_interface *iface, const struct usb_device_id *id) { + struct usb_device *udev = interface_to_usbdev(iface); struct i1480_usb *i1480_usb; struct i1480 *i1480; struct device *dev = &iface->dev; @@ -352,8 +353,8 @@ int i1480_usb_probe(struct usb_interface *iface, const struct usb_device_id *id) iface->cur_altsetting->desc.bInterfaceNumber); goto error; } - if (iface->num_altsetting > 1 - && interface_to_usbdev(iface)->descriptor.idProduct == 0xbabe) { + if (iface->num_altsetting > 1 && + le16_to_cpu(udev->descriptor.idProduct) == 0xbabe) { /* Need altsetting #1 [HW QUIRK] or EP1 won't work */ result = usb_set_interface(interface_to_usbdev(iface), 0, 1); if (result < 0) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 52a70ee6014f..8b9049dac094 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -452,7 +452,7 @@ config DAVINCI_WATCHDOG config ORION_WATCHDOG tristate "Orion watchdog" - depends on ARCH_ORION5X || ARCH_DOVE || MACH_DOVE || ARCH_MVEBU || COMPILE_TEST + depends on ARCH_ORION5X || ARCH_DOVE || MACH_DOVE || ARCH_MVEBU || (COMPILE_TEST && !ARCH_EBSA110) depends on ARM select WATCHDOG_CORE help diff --git a/drivers/watchdog/bcm_kona_wdt.c b/drivers/watchdog/bcm_kona_wdt.c index 6fce17d5b9f1..a5775dfd8d5f 100644 --- a/drivers/watchdog/bcm_kona_wdt.c +++ b/drivers/watchdog/bcm_kona_wdt.c @@ -304,6 +304,8 @@ static int bcm_kona_wdt_probe(struct platform_device *pdev) if (!wdt) return -ENOMEM; + spin_lock_init(&wdt->lock); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); wdt->base = devm_ioremap_resource(dev, res); if (IS_ERR(wdt->base)) @@ -316,7 +318,6 @@ static int bcm_kona_wdt_probe(struct platform_device *pdev) return ret; } - spin_lock_init(&wdt->lock); platform_set_drvdata(pdev, wdt); watchdog_set_drvdata(&bcm_kona_wdt_wdd, wdt); bcm_kona_wdt_wdd.parent = &pdev->dev; diff --git a/drivers/watchdog/cadence_wdt.c b/drivers/watchdog/cadence_wdt.c index 8d61e8bfe60b..86e0b5d2e761 100644 --- a/drivers/watchdog/cadence_wdt.c +++ b/drivers/watchdog/cadence_wdt.c @@ -49,7 +49,7 @@ /* Counter maximum value */ #define CDNS_WDT_COUNTER_MAX 0xFFF -static int wdt_timeout = CDNS_WDT_DEFAULT_TIMEOUT; +static int wdt_timeout; static int nowayout = WATCHDOG_NOWAYOUT; module_param(wdt_timeout, int, 0); diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 347f0389b089..c4f65873bfa4 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -306,16 +306,15 @@ static int iTCO_wdt_ping(struct watchdog_device *wd_dev) iTCO_vendor_pre_keepalive(p->smi_res, wd_dev->timeout); + /* Reset the timeout status bit so that the timer + * needs to count down twice again before rebooting */ + outw(0x0008, TCO1_STS(p)); /* write 1 to clear bit */ + /* Reload the timer by writing to the TCO Timer Counter register */ - if (p->iTCO_version >= 2) { + if (p->iTCO_version >= 2) outw(0x01, TCO_RLD(p)); - } else if (p->iTCO_version == 1) { - /* Reset the timeout status bit so that the timer - * needs to count down twice again before rebooting */ - outw(0x0008, TCO1_STS(p)); /* write 1 to clear bit */ - + else if (p->iTCO_version == 1) outb(0x01, TCO_RLD(p)); - } spin_unlock(&p->io_lock); return 0; @@ -328,11 +327,8 @@ static int iTCO_wdt_set_timeout(struct watchdog_device *wd_dev, unsigned int t) unsigned char val8; unsigned int tmrval; - tmrval = seconds_to_ticks(p, t); - - /* For TCO v1 the timer counts down twice before rebooting */ - if (p->iTCO_version == 1) - tmrval /= 2; + /* The timer counts down twice before rebooting */ + tmrval = seconds_to_ticks(p, t) / 2; /* from the specs: */ /* "Values of 0h-3h are ignored and should not be attempted" */ @@ -385,6 +381,8 @@ static unsigned int iTCO_wdt_get_timeleft(struct watchdog_device *wd_dev) spin_lock(&p->io_lock); val16 = inw(TCO_RLD(p)); val16 &= 0x3ff; + if (!(inw(TCO1_STS(p)) & 0x0008)) + val16 += (inw(TCOv2_TMR(p)) & 0x3ff); spin_unlock(&p->io_lock); time_left = ticks_to_seconds(p, val16); diff --git a/drivers/watchdog/pcwd_usb.c b/drivers/watchdog/pcwd_usb.c index 99ebf6ea3de6..5615f4013924 100644 --- a/drivers/watchdog/pcwd_usb.c +++ b/drivers/watchdog/pcwd_usb.c @@ -630,6 +630,9 @@ static int usb_pcwd_probe(struct usb_interface *interface, return -ENODEV; } + if (iface_desc->desc.bNumEndpoints < 1) + return -ENODEV; + /* check out the endpoint: it has to be Interrupt & IN */ endpoint = &iface_desc->endpoint[0].desc; diff --git a/drivers/watchdog/sama5d4_wdt.c b/drivers/watchdog/sama5d4_wdt.c index f709962018ac..362fd229786d 100644 --- a/drivers/watchdog/sama5d4_wdt.c +++ b/drivers/watchdog/sama5d4_wdt.c @@ -6,6 +6,7 @@ * Licensed under GPLv2. */ +#include <linux/delay.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/kernel.h> @@ -29,6 +30,7 @@ struct sama5d4_wdt { struct watchdog_device wdd; void __iomem *reg_base; u32 mr; + unsigned long last_ping; }; static int wdt_timeout = WDT_DEFAULT_TIMEOUT; @@ -44,11 +46,34 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); +#define wdt_enabled (!(wdt->mr & AT91_WDT_WDDIS)) + #define wdt_read(wdt, field) \ readl_relaxed((wdt)->reg_base + (field)) -#define wdt_write(wtd, field, val) \ - writel_relaxed((val), (wdt)->reg_base + (field)) +/* 4 slow clock periods is 4/32768 = 122.07µs*/ +#define WDT_DELAY usecs_to_jiffies(123) + +static void wdt_write(struct sama5d4_wdt *wdt, u32 field, u32 val) +{ + /* + * WDT_CR and WDT_MR must not be modified within three slow clock + * periods following a restart of the watchdog performed by a write + * access in WDT_CR. + */ + while (time_before(jiffies, wdt->last_ping + WDT_DELAY)) + usleep_range(30, 125); + writel_relaxed(val, wdt->reg_base + field); + wdt->last_ping = jiffies; +} + +static void wdt_write_nosleep(struct sama5d4_wdt *wdt, u32 field, u32 val) +{ + if (time_before(jiffies, wdt->last_ping + WDT_DELAY)) + udelay(123); + writel_relaxed(val, wdt->reg_base + field); + wdt->last_ping = jiffies; +} static int sama5d4_wdt_start(struct watchdog_device *wdd) { @@ -89,7 +114,16 @@ static int sama5d4_wdt_set_timeout(struct watchdog_device *wdd, wdt->mr &= ~AT91_WDT_WDD; wdt->mr |= AT91_WDT_SET_WDV(value); wdt->mr |= AT91_WDT_SET_WDD(value); - wdt_write(wdt, AT91_WDT_MR, wdt->mr); + + /* + * WDDIS has to be 0 when updating WDD/WDV. The datasheet states: When + * setting the WDDIS bit, and while it is set, the fields WDV and WDD + * must not be modified. + * If the watchdog is enabled, then the timeout can be updated. Else, + * wait that the user enables it. + */ + if (wdt_enabled) + wdt_write(wdt, AT91_WDT_MR, wdt->mr & ~AT91_WDT_WDDIS); wdd->timeout = timeout; @@ -145,23 +179,21 @@ static int of_sama5d4_wdt_init(struct device_node *np, struct sama5d4_wdt *wdt) static int sama5d4_wdt_init(struct sama5d4_wdt *wdt) { - struct watchdog_device *wdd = &wdt->wdd; - u32 value = WDT_SEC2TICKS(wdd->timeout); u32 reg; - /* - * Because the fields WDV and WDD must not be modified when the WDDIS - * bit is set, so clear the WDDIS bit before writing the WDT_MR. + * When booting and resuming, the bootloader may have changed the + * watchdog configuration. + * If the watchdog is already running, we can safely update it. + * Else, we have to disable it properly. */ - reg = wdt_read(wdt, AT91_WDT_MR); - reg &= ~AT91_WDT_WDDIS; - wdt_write(wdt, AT91_WDT_MR, reg); - - wdt->mr |= AT91_WDT_SET_WDD(value); - wdt->mr |= AT91_WDT_SET_WDV(value); - - wdt_write(wdt, AT91_WDT_MR, wdt->mr); - + if (wdt_enabled) { + wdt_write_nosleep(wdt, AT91_WDT_MR, wdt->mr); + } else { + reg = wdt_read(wdt, AT91_WDT_MR); + if (!(reg & AT91_WDT_WDDIS)) + wdt_write_nosleep(wdt, AT91_WDT_MR, + reg | AT91_WDT_WDDIS); + } return 0; } @@ -172,6 +204,7 @@ static int sama5d4_wdt_probe(struct platform_device *pdev) struct resource *res; void __iomem *regs; u32 irq = 0; + u32 timeout; int ret; wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); @@ -184,6 +217,7 @@ static int sama5d4_wdt_probe(struct platform_device *pdev) wdd->ops = &sama5d4_wdt_ops; wdd->min_timeout = MIN_WDT_TIMEOUT; wdd->max_timeout = MAX_WDT_TIMEOUT; + wdt->last_ping = jiffies; watchdog_set_drvdata(wdd, wdt); @@ -221,6 +255,11 @@ static int sama5d4_wdt_probe(struct platform_device *pdev) return ret; } + timeout = WDT_SEC2TICKS(wdd->timeout); + + wdt->mr |= AT91_WDT_SET_WDD(timeout); + wdt->mr |= AT91_WDT_SET_WDV(timeout); + ret = sama5d4_wdt_init(wdt); if (ret) return ret; @@ -263,9 +302,7 @@ static int sama5d4_wdt_resume(struct device *dev) { struct sama5d4_wdt *wdt = dev_get_drvdata(dev); - wdt_write(wdt, AT91_WDT_MR, wdt->mr & ~AT91_WDT_WDDIS); - if (wdt->mr & AT91_WDT_WDDIS) - wdt_write(wdt, AT91_WDT_MR, wdt->mr); + sama5d4_wdt_init(wdt); return 0; } diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c index 48b2c058b009..bc7addc2dc06 100644 --- a/drivers/watchdog/wdt_pci.c +++ b/drivers/watchdog/wdt_pci.c @@ -332,7 +332,7 @@ static irqreturn_t wdtpci_interrupt(int irq, void *dev_id) pr_crit("Would Reboot\n"); #else pr_crit("Initiating system reboot\n"); - emergency_restart(NULL); + emergency_restart(); #endif #else pr_crit("Reset in 5ms\n"); diff --git a/drivers/watchdog/zx2967_wdt.c b/drivers/watchdog/zx2967_wdt.c index e290d5a13a6d..c98252733c30 100644 --- a/drivers/watchdog/zx2967_wdt.c +++ b/drivers/watchdog/zx2967_wdt.c @@ -211,10 +211,8 @@ static int zx2967_wdt_probe(struct platform_device *pdev) base = platform_get_resource(pdev, IORESOURCE_MEM, 0); wdt->reg_base = devm_ioremap_resource(dev, base); - if (IS_ERR(wdt->reg_base)) { - dev_err(dev, "ioremap failed\n"); + if (IS_ERR(wdt->reg_base)) return PTR_ERR(wdt->reg_base); - } zx2967_wdt_reset_sysctrl(dev); |