From 59a9ed5f87b6e396aed1f6bf7d6496f7ba66c37a Mon Sep 17 00:00:00 2001 From: Stefan Haberland Date: Tue, 23 Feb 2016 10:15:27 +0100 Subject: s390/dasd: reorder lcu and device lock Reorder lcu and device lock to get rid of the error-prone trylock mechanism. The locking order is lcu lock -> device lock. This protects against changes to the lcu device lists and enables us to iterate over the devices, take the cdev lock and make changes to the device structures. The complicated part is the summary unit check handler that gets an interrupt on one device of the lcu that leads to structural changes of the whole lcu itself. This work needs to be done even if devices on the lcu disappear. So a device independent worker is used. The old approach tried to update some lcu structures and set up the lcu worker in the interrupt context with the device lock held. But this forced the lock order "cdev lock -> lcu lock" that made it hard to have the lcu lock held and iterate over all devices and change them. The new approach is to schedule a device specific worker that gets out of the interrupt context and rid of the device lock for summary unit checks. This worker is able to take the lcu lock and schedule the lcu worker that updates all devices. The time between interrupt and worker execution is no problem because the devices in the lcu reject all I/O in this time with an appropriate error. The dasd driver can deal with this situation and re-drive the I/O later on. Signed-off-by: Stefan Haberland Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd_alias.c | 226 ++++++++++------------------------------ drivers/s390/block/dasd_eckd.c | 38 +++++-- drivers/s390/block/dasd_eckd.h | 3 +- drivers/s390/block/dasd_int.h | 2 + 4 files changed, 86 insertions(+), 183 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c index 17ad5749e91d..1e560188dd13 100644 --- a/drivers/s390/block/dasd_alias.c +++ b/drivers/s390/block/dasd_alias.c @@ -317,17 +317,17 @@ static int _add_device_to_lcu(struct alias_lcu *lcu, struct alias_pav_group *group; struct dasd_uid uid; + spin_lock(get_ccwdev_lock(device->cdev)); private->uid.type = lcu->uac->unit[private->uid.real_unit_addr].ua_type; private->uid.base_unit_addr = lcu->uac->unit[private->uid.real_unit_addr].base_ua; uid = private->uid; - + spin_unlock(get_ccwdev_lock(device->cdev)); /* if we have no PAV anyway, we don't need to bother with PAV groups */ if (lcu->pav == NO_PAV) { list_move(&device->alias_list, &lcu->active_devices); return 0; } - group = _find_group(lcu, &uid); if (!group) { group = kzalloc(sizeof(*group), GFP_ATOMIC); @@ -397,130 +397,6 @@ suborder_not_supported(struct dasd_ccw_req *cqr) return 0; } -/* - * This function tries to lock all devices on an lcu via trylock - * return NULL on success otherwise return first failed device - */ -static struct dasd_device *_trylock_all_devices_on_lcu(struct alias_lcu *lcu, - struct dasd_device *pos) - -{ - struct alias_pav_group *pavgroup; - struct dasd_device *device; - - list_for_each_entry(device, &lcu->active_devices, alias_list) { - if (device == pos) - continue; - if (!spin_trylock(get_ccwdev_lock(device->cdev))) - return device; - } - list_for_each_entry(device, &lcu->inactive_devices, alias_list) { - if (device == pos) - continue; - if (!spin_trylock(get_ccwdev_lock(device->cdev))) - return device; - } - list_for_each_entry(pavgroup, &lcu->grouplist, group) { - list_for_each_entry(device, &pavgroup->baselist, alias_list) { - if (device == pos) - continue; - if (!spin_trylock(get_ccwdev_lock(device->cdev))) - return device; - } - list_for_each_entry(device, &pavgroup->aliaslist, alias_list) { - if (device == pos) - continue; - if (!spin_trylock(get_ccwdev_lock(device->cdev))) - return device; - } - } - return NULL; -} - -/* - * unlock all devices except the one that is specified as pos - * stop if enddev is specified and reached - */ -static void _unlock_all_devices_on_lcu(struct alias_lcu *lcu, - struct dasd_device *pos, - struct dasd_device *enddev) - -{ - struct alias_pav_group *pavgroup; - struct dasd_device *device; - - list_for_each_entry(device, &lcu->active_devices, alias_list) { - if (device == pos) - continue; - if (device == enddev) - return; - spin_unlock(get_ccwdev_lock(device->cdev)); - } - list_for_each_entry(device, &lcu->inactive_devices, alias_list) { - if (device == pos) - continue; - if (device == enddev) - return; - spin_unlock(get_ccwdev_lock(device->cdev)); - } - list_for_each_entry(pavgroup, &lcu->grouplist, group) { - list_for_each_entry(device, &pavgroup->baselist, alias_list) { - if (device == pos) - continue; - if (device == enddev) - return; - spin_unlock(get_ccwdev_lock(device->cdev)); - } - list_for_each_entry(device, &pavgroup->aliaslist, alias_list) { - if (device == pos) - continue; - if (device == enddev) - return; - spin_unlock(get_ccwdev_lock(device->cdev)); - } - } -} - -/* - * this function is needed because the locking order - * device lock -> lcu lock - * needs to be assured when iterating over devices in an LCU - * - * if a device is specified in pos then the device lock is already hold - */ -static void _trylock_and_lock_lcu_irqsave(struct alias_lcu *lcu, - struct dasd_device *pos, - unsigned long *flags) -{ - struct dasd_device *failed; - - do { - spin_lock_irqsave(&lcu->lock, *flags); - failed = _trylock_all_devices_on_lcu(lcu, pos); - if (failed) { - _unlock_all_devices_on_lcu(lcu, pos, failed); - spin_unlock_irqrestore(&lcu->lock, *flags); - cpu_relax(); - } - } while (failed); -} - -static void _trylock_and_lock_lcu(struct alias_lcu *lcu, - struct dasd_device *pos) -{ - struct dasd_device *failed; - - do { - spin_lock(&lcu->lock); - failed = _trylock_all_devices_on_lcu(lcu, pos); - if (failed) { - _unlock_all_devices_on_lcu(lcu, pos, failed); - spin_unlock(&lcu->lock); - cpu_relax(); - } - } while (failed); -} - static int read_unit_address_configuration(struct dasd_device *device, struct alias_lcu *lcu) { @@ -615,7 +491,7 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu) if (rc) return rc; - _trylock_and_lock_lcu_irqsave(lcu, NULL, &flags); + spin_lock_irqsave(&lcu->lock, flags); lcu->pav = NO_PAV; for (i = 0; i < MAX_DEVICES_PER_LCU; ++i) { switch (lcu->uac->unit[i].ua_type) { @@ -634,7 +510,6 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu) alias_list) { _add_device_to_lcu(lcu, device, refdev); } - _unlock_all_devices_on_lcu(lcu, NULL, NULL); spin_unlock_irqrestore(&lcu->lock, flags); return 0; } @@ -722,8 +597,7 @@ int dasd_alias_add_device(struct dasd_device *device) lcu = private->lcu; rc = 0; - spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); - spin_lock(&lcu->lock); + spin_lock_irqsave(&lcu->lock, flags); if (!(lcu->flags & UPDATE_PENDING)) { rc = _add_device_to_lcu(lcu, device, device); if (rc) @@ -733,8 +607,7 @@ int dasd_alias_add_device(struct dasd_device *device) list_move(&device->alias_list, &lcu->active_devices); _schedule_lcu_update(lcu, device); } - spin_unlock(&lcu->lock); - spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); + spin_unlock_irqrestore(&lcu->lock, flags); return rc; } @@ -933,15 +806,27 @@ static void _stop_all_devices_on_lcu(struct alias_lcu *lcu) struct alias_pav_group *pavgroup; struct dasd_device *device; - list_for_each_entry(device, &lcu->active_devices, alias_list) + list_for_each_entry(device, &lcu->active_devices, alias_list) { + spin_lock(get_ccwdev_lock(device->cdev)); dasd_device_set_stop_bits(device, DASD_STOPPED_SU); - list_for_each_entry(device, &lcu->inactive_devices, alias_list) + spin_unlock(get_ccwdev_lock(device->cdev)); + } + list_for_each_entry(device, &lcu->inactive_devices, alias_list) { + spin_lock(get_ccwdev_lock(device->cdev)); dasd_device_set_stop_bits(device, DASD_STOPPED_SU); + spin_unlock(get_ccwdev_lock(device->cdev)); + } list_for_each_entry(pavgroup, &lcu->grouplist, group) { - list_for_each_entry(device, &pavgroup->baselist, alias_list) + list_for_each_entry(device, &pavgroup->baselist, alias_list) { + spin_lock(get_ccwdev_lock(device->cdev)); dasd_device_set_stop_bits(device, DASD_STOPPED_SU); - list_for_each_entry(device, &pavgroup->aliaslist, alias_list) + spin_unlock(get_ccwdev_lock(device->cdev)); + } + list_for_each_entry(device, &pavgroup->aliaslist, alias_list) { + spin_lock(get_ccwdev_lock(device->cdev)); dasd_device_set_stop_bits(device, DASD_STOPPED_SU); + spin_unlock(get_ccwdev_lock(device->cdev)); + } } } @@ -950,15 +835,27 @@ static void _unstop_all_devices_on_lcu(struct alias_lcu *lcu) struct alias_pav_group *pavgroup; struct dasd_device *device; - list_for_each_entry(device, &lcu->active_devices, alias_list) + list_for_each_entry(device, &lcu->active_devices, alias_list) { + spin_lock(get_ccwdev_lock(device->cdev)); dasd_device_remove_stop_bits(device, DASD_STOPPED_SU); - list_for_each_entry(device, &lcu->inactive_devices, alias_list) + spin_unlock(get_ccwdev_lock(device->cdev)); + } + list_for_each_entry(device, &lcu->inactive_devices, alias_list) { + spin_lock(get_ccwdev_lock(device->cdev)); dasd_device_remove_stop_bits(device, DASD_STOPPED_SU); + spin_unlock(get_ccwdev_lock(device->cdev)); + } list_for_each_entry(pavgroup, &lcu->grouplist, group) { - list_for_each_entry(device, &pavgroup->baselist, alias_list) + list_for_each_entry(device, &pavgroup->baselist, alias_list) { + spin_lock(get_ccwdev_lock(device->cdev)); dasd_device_remove_stop_bits(device, DASD_STOPPED_SU); - list_for_each_entry(device, &pavgroup->aliaslist, alias_list) + spin_unlock(get_ccwdev_lock(device->cdev)); + } + list_for_each_entry(device, &pavgroup->aliaslist, alias_list) { + spin_lock(get_ccwdev_lock(device->cdev)); dasd_device_remove_stop_bits(device, DASD_STOPPED_SU); + spin_unlock(get_ccwdev_lock(device->cdev)); + } } } @@ -984,48 +881,32 @@ static void summary_unit_check_handling_work(struct work_struct *work) spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); reset_summary_unit_check(lcu, device, suc_data->reason); - _trylock_and_lock_lcu_irqsave(lcu, NULL, &flags); + spin_lock_irqsave(&lcu->lock, flags); _unstop_all_devices_on_lcu(lcu); _restart_all_base_devices_on_lcu(lcu); /* 3. read new alias configuration */ _schedule_lcu_update(lcu, device); lcu->suc_data.device = NULL; dasd_put_device(device); - _unlock_all_devices_on_lcu(lcu, NULL, NULL); spin_unlock_irqrestore(&lcu->lock, flags); } -/* - * note: this will be called from int handler context (cdev locked) - */ -void dasd_alias_handle_summary_unit_check(struct dasd_device *device, - struct irb *irb) +void dasd_alias_handle_summary_unit_check(struct work_struct *work) { + struct dasd_device *device = container_of(work, struct dasd_device, + suc_work); struct dasd_eckd_private *private = device->private; struct alias_lcu *lcu; - char reason; - char *sense; - - sense = dasd_get_sense(irb); - if (sense) { - reason = sense[8]; - DBF_DEV_EVENT(DBF_NOTICE, device, "%s %x", - "eckd handle summary unit check: reason", reason); - } else { - DBF_DEV_EVENT(DBF_WARNING, device, "%s", - "eckd handle summary unit check:" - " no reason code available"); - return; - } + unsigned long flags; lcu = private->lcu; if (!lcu) { DBF_DEV_EVENT(DBF_WARNING, device, "%s", "device not ready to handle summary" " unit check (no lcu structure)"); - return; + goto out; } - _trylock_and_lock_lcu(lcu, device); + spin_lock_irqsave(&lcu->lock, flags); /* If this device is about to be removed just return and wait for * the next interrupt on a different device */ @@ -1033,27 +914,26 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device, DBF_DEV_EVENT(DBF_WARNING, device, "%s", "device is in offline processing," " don't do summary unit check handling"); - _unlock_all_devices_on_lcu(lcu, device, NULL); - spin_unlock(&lcu->lock); - return; + goto out_unlock; } if (lcu->suc_data.device) { /* already scheduled or running */ DBF_DEV_EVENT(DBF_WARNING, device, "%s", "previous instance of summary unit check worker" " still pending"); - _unlock_all_devices_on_lcu(lcu, device, NULL); - spin_unlock(&lcu->lock); - return ; + goto out_unlock; } _stop_all_devices_on_lcu(lcu); /* prepare for lcu_update */ - private->lcu->flags |= NEED_UAC_UPDATE | UPDATE_PENDING; - lcu->suc_data.reason = reason; + lcu->flags |= NEED_UAC_UPDATE | UPDATE_PENDING; + lcu->suc_data.reason = private->suc_reason; lcu->suc_data.device = device; dasd_get_device(device); - _unlock_all_devices_on_lcu(lcu, device, NULL); - spin_unlock(&lcu->lock); if (!schedule_work(&lcu->suc_data.worker)) dasd_put_device(device); +out_unlock: + spin_unlock_irqrestore(&lcu->lock, flags); +out: + clear_bit(DASD_FLAG_SUC, &device->flags); + dasd_put_device(device); }; diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 75c032dcf173..c1b4ae55e129 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -1682,6 +1682,8 @@ dasd_eckd_check_characteristics(struct dasd_device *device) /* setup work queue for validate server*/ INIT_WORK(&device->kick_validate, dasd_eckd_do_validate_server); + /* setup work queue for summary unit check */ + INIT_WORK(&device->suc_work, dasd_alias_handle_summary_unit_check); if (!ccw_device_is_pathgroup(device->cdev)) { dev_warn(&device->cdev->dev, @@ -2549,14 +2551,6 @@ static void dasd_eckd_check_for_device_change(struct dasd_device *device, device->state == DASD_STATE_ONLINE && !test_bit(DASD_FLAG_OFFLINE, &device->flags) && !test_bit(DASD_FLAG_SUSPENDED, &device->flags)) { - /* - * the state change could be caused by an alias - * reassignment remove device from alias handling - * to prevent new requests from being scheduled on - * the wrong alias device - */ - dasd_alias_remove_device(device); - /* schedule worker to reload device */ dasd_reload_device(device); } @@ -2571,7 +2565,27 @@ static void dasd_eckd_check_for_device_change(struct dasd_device *device, /* summary unit check */ if ((sense[27] & DASD_SENSE_BIT_0) && (sense[7] == 0x0D) && (scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK)) { - dasd_alias_handle_summary_unit_check(device, irb); + if (test_and_set_bit(DASD_FLAG_SUC, &device->flags)) { + DBF_DEV_EVENT(DBF_WARNING, device, "%s", + "eckd suc: device already notified"); + return; + } + sense = dasd_get_sense(irb); + if (!sense) { + DBF_DEV_EVENT(DBF_WARNING, device, "%s", + "eckd suc: no reason code available"); + clear_bit(DASD_FLAG_SUC, &device->flags); + return; + + } + private->suc_reason = sense[8]; + DBF_DEV_EVENT(DBF_NOTICE, device, "%s %x", + "eckd handle summary unit check: reason", + private->suc_reason); + dasd_get_device(device); + if (!schedule_work(&device->suc_work)) + dasd_put_device(device); + return; } @@ -4495,6 +4509,12 @@ static int dasd_eckd_reload_device(struct dasd_device *device) struct dasd_uid uid; unsigned long flags; + /* + * remove device from alias handling to prevent new requests + * from being scheduled on the wrong alias device + */ + dasd_alias_remove_device(device); + spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); old_base = private->uid.base_unit_addr; spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index f8f91ee652d3..6d9a6d3517cd 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h @@ -525,6 +525,7 @@ struct dasd_eckd_private { int count; u32 fcx_max_data; + char suc_reason; }; @@ -534,7 +535,7 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *); int dasd_alias_add_device(struct dasd_device *); int dasd_alias_remove_device(struct dasd_device *); struct dasd_device *dasd_alias_get_start_dev(struct dasd_device *); -void dasd_alias_handle_summary_unit_check(struct dasd_device *, struct irb *); +void dasd_alias_handle_summary_unit_check(struct work_struct *); void dasd_eckd_reset_ccw_to_base_io(struct dasd_ccw_req *); void dasd_alias_lcu_setup_complete(struct dasd_device *); void dasd_alias_wait_for_lcu_setup(struct dasd_device *); diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 8de29be32a56..0f0add932e7a 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -470,6 +470,7 @@ struct dasd_device { struct work_struct restore_device; struct work_struct reload_device; struct work_struct kick_validate; + struct work_struct suc_work; struct timer_list timer; debug_info_t *debug_area; @@ -542,6 +543,7 @@ struct dasd_attention_data { #define DASD_FLAG_SAFE_OFFLINE_RUNNING 11 /* safe offline running */ #define DASD_FLAG_ABORTALL 12 /* Abort all noretry requests */ #define DASD_FLAG_PATH_VERIFY 13 /* Path verification worker running */ +#define DASD_FLAG_SUC 14 /* unhandled summary unit check */ #define DASD_SLEEPON_START_TAG ((void *) 1) #define DASD_SLEEPON_END_TAG ((void *) 2) -- cgit From eccf432f6542d9895d6c50edb5634c6147918ed2 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 8 Feb 2016 15:31:45 +0100 Subject: ide: icside: remove incorrect initconst annotation The icside_probe function can be called for hotplugged devices, so its reference to the __initconst icside_v6_port_info variable may be invalid, as Kbuild points out: WARNING: drivers/ide/icside.o(.text+0x338): Section mismatch in reference from the function icside_probe() to the (unknown reference) .init.rodata:(unknown) Interestingly, this problem only shows up with clang but not with gcc, which optimizes out the __initconst variable. This removes the incorrect annotation. Signed-off-by: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/ide/icside.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c index 9f0a48e39b8a..80e933b296f6 100644 --- a/drivers/ide/icside.c +++ b/drivers/ide/icside.c @@ -451,7 +451,7 @@ err_free: return ret; } -static const struct ide_port_info icside_v6_port_info __initconst = { +static const struct ide_port_info icside_v6_port_info = { .init_dma = icside_dma_off_init, .port_ops = &icside_v6_no_dma_port_ops, .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO, -- cgit From 0d7ef45cdeebcc95d581703f45f6de7b2ee89b8d Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 2 Mar 2016 23:33:32 +0100 Subject: ide: palm_bk3710: test clock rate to avoid division by 0 The clk API may return 0 on clk_get_rate, so we should check the result before using it as a divisor. Signed-off-by: Wolfram Sang Signed-off-by: David S. Miller --- drivers/ide/palm_bk3710.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/ide/palm_bk3710.c b/drivers/ide/palm_bk3710.c index 8012e43bf8f6..46427ea01753 100644 --- a/drivers/ide/palm_bk3710.c +++ b/drivers/ide/palm_bk3710.c @@ -325,6 +325,8 @@ static int __init palm_bk3710_probe(struct platform_device *pdev) clk_enable(clk); rate = clk_get_rate(clk); + if (!rate) + return -EINVAL; /* NOTE: round *down* to meet minimum timings; we count in clocks */ ideclk_period = 1000000000UL / rate; -- cgit From 4016260ba47a43ec67d4bf3610be37fcb2e416d7 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 23 Mar 2016 07:10:17 -0400 Subject: drm/msm: fix bug after preclose removal commit 53190c7194d9a8337fe419134e44c30eb63ebd08 Author: Daniel Vetter AuthorDate: Mon Jan 25 22:16:49 2016 +0100 Commit: Daniel Vetter CommitDate: Mon Feb 8 09:55:50 2016 +0100 drm/msm: Nuke preclose hooks Left around the unused (and null) preclose fxn ptr, and things predictibly explode when you try to call that. Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_drv.c | 3 --- drivers/gpu/drm/msm/msm_kms.h | 1 - 2 files changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index d52910e2c26c..c03b96709179 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -467,9 +467,6 @@ static void msm_preclose(struct drm_device *dev, struct drm_file *file) struct msm_file_private *ctx = file->driver_priv; struct msm_kms *kms = priv->kms; - if (kms) - kms->funcs->preclose(kms, file); - mutex_lock(&dev->struct_mutex); if (ctx == priv->lastctx) priv->lastctx = NULL; diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h index 9bcabaada179..e32222c3d44f 100644 --- a/drivers/gpu/drm/msm/msm_kms.h +++ b/drivers/gpu/drm/msm/msm_kms.h @@ -55,7 +55,6 @@ struct msm_kms_funcs { struct drm_encoder *slave_encoder, bool is_cmd_mode); /* cleanup: */ - void (*preclose)(struct msm_kms *kms, struct drm_file *file); void (*destroy)(struct msm_kms *kms); }; -- cgit From 0a69509f24ebf3e701bf1df6e2673ca16bdbe5c9 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 23 Mar 2016 10:09:00 -0400 Subject: drm/msm: fix typo in the !COMMON_CLK case Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/hdmi/hdmi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h index b04a64664673..65428cf233ce 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h @@ -196,7 +196,7 @@ void __exit msm_hdmi_phy_driver_unregister(void); int msm_hdmi_pll_8960_init(struct platform_device *pdev); int msm_hdmi_pll_8996_init(struct platform_device *pdev); #else -static inline int msm_hdmi_pll_8960_init(struct platform_device *pdev); +static inline int msm_hdmi_pll_8960_init(struct platform_device *pdev) { return -ENODEV; } -- cgit From 526131262223e9315bfd41213f5a76e792f184ff Mon Sep 17 00:00:00 2001 From: Qianqian Xie Date: Thu, 24 Mar 2016 19:08:00 +0800 Subject: net: hns: fix a bug for cycle index The cycle index should be varied while the variable j is a fixed value. The patch will fix this bug. Signed-off-by: Qianqian Xie Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 5c1ac9ba1bf2..5978a5c8ef35 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -2219,17 +2219,17 @@ void hns_dsaf_get_regs(struct dsaf_device *ddev, u32 port, void *data) /* dsaf onode registers */ for (i = 0; i < DSAF_XOD_NUM; i++) { p[311 + i] = dsaf_read_dev(ddev, - DSAF_XOD_ETS_TSA_TC0_TC3_CFG_0_REG + j * 0x90); + DSAF_XOD_ETS_TSA_TC0_TC3_CFG_0_REG + i * 0x90); p[319 + i] = dsaf_read_dev(ddev, - DSAF_XOD_ETS_TSA_TC4_TC7_CFG_0_REG + j * 0x90); + DSAF_XOD_ETS_TSA_TC4_TC7_CFG_0_REG + i * 0x90); p[327 + i] = dsaf_read_dev(ddev, - DSAF_XOD_ETS_BW_TC0_TC3_CFG_0_REG + j * 0x90); + DSAF_XOD_ETS_BW_TC0_TC3_CFG_0_REG + i * 0x90); p[335 + i] = dsaf_read_dev(ddev, - DSAF_XOD_ETS_BW_TC4_TC7_CFG_0_REG + j * 0x90); + DSAF_XOD_ETS_BW_TC4_TC7_CFG_0_REG + i * 0x90); p[343 + i] = dsaf_read_dev(ddev, - DSAF_XOD_ETS_BW_OFFSET_CFG_0_REG + j * 0x90); + DSAF_XOD_ETS_BW_OFFSET_CFG_0_REG + i * 0x90); p[351 + i] = dsaf_read_dev(ddev, - DSAF_XOD_ETS_TOKEN_CFG_0_REG + j * 0x90); + DSAF_XOD_ETS_TOKEN_CFG_0_REG + i * 0x90); } p[359] = dsaf_read_dev(ddev, DSAF_XOD_PFS_CFG_0_0_REG + port * 0x90); -- cgit From 8d71397bd2021f8ef68ae34d8bea431cc903fcdd Mon Sep 17 00:00:00 2001 From: Qianqian Xie Date: Thu, 24 Mar 2016 19:08:01 +0800 Subject: net: hns: optimizate fmt of snprintf() It misses string format in function snprintf(), as below: snprintf(buff, ETH_GSTRING_LEN, g_gmac_stats_string[i].desc); It needs to add "%s" to fix it as below: snprintf(buff, ETH_GSTRING_LEN, "%s", g_gmac_stats_string[i].desc); Signed-off-by: Qianqian Xie Signed-off-by: Kejian Yan Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c index 6e2b76ede075..44abb08de155 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c @@ -664,7 +664,8 @@ static void hns_gmac_get_strings(u32 stringset, u8 *data) return; for (i = 0; i < ARRAY_SIZE(g_gmac_stats_string); i++) { - snprintf(buff, ETH_GSTRING_LEN, g_gmac_stats_string[i].desc); + snprintf(buff, ETH_GSTRING_LEN, "%s", + g_gmac_stats_string[i].desc); buff = buff + ETH_GSTRING_LEN; } } -- cgit From 055a94177dfa0bcbf2c4be475fef56bc80c9a233 Mon Sep 17 00:00:00 2001 From: Qianqian Xie Date: Thu, 24 Mar 2016 19:08:02 +0800 Subject: net: hns: bug fix for return values The return values in the first two functions mdiobus_write() are ignored. The patch will fix it. Signed-off-by: Qianqian Xie Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_ethtool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c index 9c3ba65988e1..0e7da3f0a564 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c @@ -1013,8 +1013,8 @@ int hns_phy_led_set(struct net_device *netdev, int value) struct phy_device *phy_dev = priv->phy; retval = phy_write(phy_dev, HNS_PHY_PAGE_REG, HNS_PHY_PAGE_LED); - retval = phy_write(phy_dev, HNS_LED_FC_REG, value); - retval = phy_write(phy_dev, HNS_PHY_PAGE_REG, HNS_PHY_PAGE_COPPER); + retval |= phy_write(phy_dev, HNS_LED_FC_REG, value); + retval |= phy_write(phy_dev, HNS_PHY_PAGE_REG, HNS_PHY_PAGE_COPPER); if (retval) { netdev_err(netdev, "mdiobus_write fail !\n"); return retval; -- cgit From 1c3bae6e475fed5c570ac16fef2afe743c477886 Mon Sep 17 00:00:00 2001 From: Qianqian Xie Date: Thu, 24 Mar 2016 19:08:03 +0800 Subject: net: hns: remove useless variable assignment and comment The variable head in hns_nic_tx_fini_pro has read a value, but it is obviously no use. The patch will fix it. And the comment is nothing to do with the routine, so it has to be removed Signed-off-by: Qianqian Xie Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_enet.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 71aa37b4b338..f0c9a41a7443 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -913,10 +913,7 @@ static int hns_nic_tx_poll_one(struct hns_nic_ring_data *ring_data, static void hns_nic_tx_fini_pro(struct hns_nic_ring_data *ring_data) { struct hnae_ring *ring = ring_data->ring; - int head = ring->next_to_clean; - - /* for hardware bug fixed */ - head = readl_relaxed(ring->io_base + RCB_REG_HEAD); + int head = readl_relaxed(ring->io_base + RCB_REG_HEAD); if (head != ring->next_to_clean) { ring_data->ring->q->handle->dev->ops->toggle_ring_irq( -- cgit From 4b34aa412c1213912608742b4d016f616b23d9e2 Mon Sep 17 00:00:00 2001 From: Sheng Li Date: Thu, 24 Mar 2016 19:08:04 +0800 Subject: net: hns: optimizate irq proccess for HNS V2 In hns V1, common_poll should check and clean fbd pkts, because it can not pend irq to clean them if there is no new pkt comes in. But hns V2 hw fixes this bug, and will pend irq itself to do this. So, for hns V2, we set ring_data->fini_process to NULL. Signed-off-by: Sheng Li Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_enet.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index f0c9a41a7443..66d1652ffbed 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -956,8 +956,8 @@ static int hns_nic_common_poll(struct napi_struct *napi, int budget) napi_complete(napi); ring_data->ring->q->handle->dev->ops->toggle_ring_irq( ring_data->ring, 0); - - ring_data->fini_process(ring_data); + if (ring_data->fini_process) + ring_data->fini_process(ring_data); return 0; } @@ -1720,6 +1720,7 @@ static int hns_nic_init_ring_data(struct hns_nic_priv *priv) { struct hnae_handle *h = priv->ae_handle; struct hns_nic_ring_data *rd; + bool is_ver1 = AE_IS_VER1(priv->enet_ver); int i; if (h->q_num > NIC_MAX_Q_PER_VF) { @@ -1737,7 +1738,7 @@ static int hns_nic_init_ring_data(struct hns_nic_priv *priv) rd->queue_index = i; rd->ring = &h->qs[i]->tx_ring; rd->poll_one = hns_nic_tx_poll_one; - rd->fini_process = hns_nic_tx_fini_pro; + rd->fini_process = is_ver1 ? hns_nic_tx_fini_pro : NULL; netif_napi_add(priv->netdev, &rd->napi, hns_nic_common_poll, NIC_TX_CLEAN_MAX_NUM); @@ -1749,7 +1750,7 @@ static int hns_nic_init_ring_data(struct hns_nic_priv *priv) rd->ring = &h->qs[i - h->q_num]->rx_ring; rd->poll_one = hns_nic_rx_poll_one; rd->ex_process = hns_nic_rx_up_pro; - rd->fini_process = hns_nic_rx_fini_pro; + rd->fini_process = is_ver1 ? hns_nic_rx_fini_pro : NULL; netif_napi_add(priv->netdev, &rd->napi, hns_nic_common_poll, NIC_RX_CLEAN_MAX_NUM); -- cgit From daa8cfd9da728b9e35c49311b23127a8859a5f3b Mon Sep 17 00:00:00 2001 From: Kejian Yan Date: Thu, 24 Mar 2016 19:08:05 +0800 Subject: net: hns: fix warning of passing zero to 'PTR_ERR' There is a misuse of PTR as shown below: ae_node = (void *)of_parse_phandle(dev->of_node, "ae-handle", 0); if (IS_ERR_OR_NULL(ae_node)) { ret = PTR_ERR(ae_node); dev_err(dev, "not find ae-handle\n"); goto out_read_prop_fail; } if the ae_node is NULL, PTR_ERR(ae_node) means it returns success. And the return value should be -ENODEV. Signed-off-by: Kejian Yan Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_enet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 66d1652ffbed..687204b780b0 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -1814,7 +1814,7 @@ static int hns_nic_try_get_ae(struct net_device *ndev) h = hnae_get_handle(&priv->netdev->dev, priv->ae_node, priv->port_id, NULL); if (IS_ERR_OR_NULL(h)) { - ret = PTR_ERR(h); + ret = -ENODEV; dev_dbg(priv->dev, "has not handle, register notifier!\n"); goto out; } -- cgit From c1203fe7bb34e2fe7d281882bcce8b6f107df038 Mon Sep 17 00:00:00 2001 From: Sheng Li Date: Thu, 24 Mar 2016 19:08:06 +0800 Subject: net: hns: bug fix about getting hilink status for HNS v2 The hilink status reg in HNS V2 is different from HNS v1. In HNS V2, It distinguishes differnt lane status according to the bit-field of the reg. As is shown below: [0:0] ---> lane0 [1:1] ---> lane1 ... But the current driver reads the reg to get the hilink status ONLY concidering HNS V1 situation. Here is a patch to support both of them. Signed-off-by: Sheng Li Signed-off-by: Daode Huang Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c | 40 ++++++++++++---------- drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h | 2 ++ 2 files changed, 24 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c index 607c3be42241..e69b02287c44 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c @@ -244,31 +244,35 @@ void hns_ppe_com_srst(struct ppe_common_cb *ppe_common, u32 val) */ phy_interface_t hns_mac_get_phy_if(struct hns_mac_cb *mac_cb) { - u32 hilink3_mode; - u32 hilink4_mode; + u32 mode; + u32 reg; + u32 shift; + bool is_ver1 = AE_IS_VER1(mac_cb->dsaf_dev->dsaf_ver); void __iomem *sys_ctl_vaddr = mac_cb->sys_ctl_vaddr; - int dev_id = mac_cb->mac_id; + int mac_id = mac_cb->mac_id; phy_interface_t phy_if = PHY_INTERFACE_MODE_NA; - hilink3_mode = dsaf_read_reg(sys_ctl_vaddr, HNS_MAC_HILINK3_REG); - hilink4_mode = dsaf_read_reg(sys_ctl_vaddr, HNS_MAC_HILINK4_REG); - if (dev_id >= 0 && dev_id <= 3) { - if (hilink4_mode == 0) - phy_if = PHY_INTERFACE_MODE_SGMII; - else + if (is_ver1 && (mac_id >= 6 && mac_id <= 7)) { + phy_if = PHY_INTERFACE_MODE_SGMII; + } else if (mac_id >= 0 && mac_id <= 3) { + reg = is_ver1 ? HNS_MAC_HILINK4_REG : HNS_MAC_HILINK4V2_REG; + mode = dsaf_read_reg(sys_ctl_vaddr, reg); + /* mac_id 0, 1, 2, 3 ---> hilink4 lane 0, 1, 2, 3 */ + shift = is_ver1 ? 0 : mac_id; + if (dsaf_get_bit(mode, shift)) phy_if = PHY_INTERFACE_MODE_XGMII; - } else if (dev_id >= 4 && dev_id <= 5) { - if (hilink3_mode == 0) - phy_if = PHY_INTERFACE_MODE_SGMII; else + phy_if = PHY_INTERFACE_MODE_SGMII; + } else if (mac_id >= 4 && mac_id <= 7) { + reg = is_ver1 ? HNS_MAC_HILINK3_REG : HNS_MAC_HILINK3V2_REG; + mode = dsaf_read_reg(sys_ctl_vaddr, reg); + /* mac_id 4, 5, 6, 7 ---> hilink3 lane 2, 3, 0, 1 */ + shift = is_ver1 ? 0 : mac_id <= 5 ? mac_id - 2 : mac_id - 6; + if (dsaf_get_bit(mode, shift)) phy_if = PHY_INTERFACE_MODE_XGMII; - } else { - phy_if = PHY_INTERFACE_MODE_SGMII; + else + phy_if = PHY_INTERFACE_MODE_SGMII; } - - dev_dbg(mac_cb->dev, - "hilink3_mode=%d, hilink4_mode=%d dev_id=%d, phy_if=%d\n", - hilink3_mode, hilink4_mode, dev_id, phy_if); return phy_if; } diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h index bf62687e5ea7..e2206f938a9c 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h @@ -103,6 +103,8 @@ /*serdes offset**/ #define HNS_MAC_HILINK3_REG DSAF_SUB_SC_HILINK3_CRG_CTRL0_REG #define HNS_MAC_HILINK4_REG DSAF_SUB_SC_HILINK4_CRG_CTRL0_REG +#define HNS_MAC_HILINK3V2_REG DSAF_SUB_SC_HILINK3_CRG_CTRL1_REG +#define HNS_MAC_HILINK4V2_REG DSAF_SUB_SC_HILINK4_CRG_CTRL1_REG #define HNS_MAC_LANE0_CTLEDFE_REG 0x000BFFCCULL #define HNS_MAC_LANE1_CTLEDFE_REG 0x000BFFBCULL #define HNS_MAC_LANE2_CTLEDFE_REG 0x000BFFACULL -- cgit From ba5049945421b8d2f3e2af786a15d13b82316503 Mon Sep 17 00:00:00 2001 From: Cyrille Pitchen Date: Thu, 24 Mar 2016 15:40:04 +0100 Subject: net: macb: replace macb_writel() call by queue_writel() to update queue ISR macb_interrupt() should not use macb_writel(bp, ISR, ) but only queue_writel(queue, ISR, ). There is one IRQ and one set of {ISR, IER, IDR, IMR} [1] registers per queue on gem hardware, though only queue0 is actually used for now to receive frames: other queues can already be used to transmit frames. The queue_readl() and queue_writel() helper macros are designed to access the relevant IRQ registers. [1] ISR: Interrupt Status Register IER: Interrupt Enable Register IDR: Interrupt Disable Register IMR: Interrupt Mask Register Signed-off-by: Cyrille Pitchen Fixes: bfbb92c44670 ("net: macb: Handle the RXUBR interrupt on all devices") Acked-by: Nicolas Ferre Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 6619178ed77b..f715352a9b85 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -1100,7 +1100,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) macb_writel(bp, NCR, ctrl | MACB_BIT(RE)); if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) - macb_writel(bp, ISR, MACB_BIT(RXUBR)); + queue_writel(queue, ISR, MACB_BIT(RXUBR)); } if (status & MACB_BIT(ISR_ROVR)) { -- cgit From 55868120a3e5420bf5aa26a816c07d691579c9e6 Mon Sep 17 00:00:00 2001 From: Petri Gynther Date: Thu, 24 Mar 2016 11:27:20 -0700 Subject: net: bcmgenet: fix dev->stats.tx_bytes accounting 1. Add bytes_compl local variable to __bcmgenet_tx_reclaim() to collect transmitted bytes. dev->stats updates can then be moved outside the while-loop. bytes_compl is also needed for future BQL support. 2. When bcmgenet device uses Tx checksum offload, each transmitted skb gets an extra 64-byte header prepended to it. Before this header is prepended to the skb, we need to save the skb "wire" length in GENET_CB(skb)->bytes_sent, so that proper Tx bytes accounting can be done in __bcmgenet_tx_reclaim(). 3. skb->len covers the entire length of skb, whether it is linear or fragmented. Thus, when we clean the fragments, do not increase transmitted bytes. Fixes: 1c1008c793fa ("net: bcmgenet: add main driver file") Signed-off-by: Petri Gynther Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 14 ++++++++++---- drivers/net/ethernet/broadcom/genet/bcmgenet.h | 6 ++++++ 2 files changed, 16 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 6746fd03cb3a..c1c7c0e6fb7c 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -1171,6 +1171,7 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev, struct enet_cb *tx_cb_ptr; struct netdev_queue *txq; unsigned int pkts_compl = 0; + unsigned int bytes_compl = 0; unsigned int c_index; unsigned int txbds_ready; unsigned int txbds_processed = 0; @@ -1193,16 +1194,13 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev, tx_cb_ptr = &priv->tx_cbs[ring->clean_ptr]; if (tx_cb_ptr->skb) { pkts_compl++; - dev->stats.tx_packets++; - dev->stats.tx_bytes += tx_cb_ptr->skb->len; + bytes_compl += GENET_CB(tx_cb_ptr->skb)->bytes_sent; dma_unmap_single(&dev->dev, dma_unmap_addr(tx_cb_ptr, dma_addr), dma_unmap_len(tx_cb_ptr, dma_len), DMA_TO_DEVICE); bcmgenet_free_cb(tx_cb_ptr); } else if (dma_unmap_addr(tx_cb_ptr, dma_addr)) { - dev->stats.tx_bytes += - dma_unmap_len(tx_cb_ptr, dma_len); dma_unmap_page(&dev->dev, dma_unmap_addr(tx_cb_ptr, dma_addr), dma_unmap_len(tx_cb_ptr, dma_len), @@ -1220,6 +1218,9 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev, ring->free_bds += txbds_processed; ring->c_index = (ring->c_index + txbds_processed) & DMA_C_INDEX_MASK; + dev->stats.tx_packets += pkts_compl; + dev->stats.tx_bytes += bytes_compl; + if (ring->free_bds > (MAX_SKB_FRAGS + 1)) { txq = netdev_get_tx_queue(dev, ring->queue); if (netif_tx_queue_stopped(txq)) @@ -1464,6 +1465,11 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev) goto out; } + /* Retain how many bytes will be sent on the wire, without TSB inserted + * by transmit checksum offload + */ + GENET_CB(skb)->bytes_sent = skb->len; + /* set the SKB transmit checksum */ if (priv->desc_64b_en) { skb = bcmgenet_put_tx_csum(dev, skb); diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h index 967367557309..1e2dc34d331a 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h @@ -531,6 +531,12 @@ struct bcmgenet_hw_params { u32 flags; }; +struct bcmgenet_skb_cb { + unsigned int bytes_sent; /* bytes on the wire (no TSB) */ +}; + +#define GENET_CB(skb) ((struct bcmgenet_skb_cb *)((skb)->cb)) + struct bcmgenet_tx_ring { spinlock_t lock; /* ring lock */ struct napi_struct napi; /* NAPI per tx queue */ -- cgit From 7dd399130efb5a454daf24075b7563d197114e39 Mon Sep 17 00:00:00 2001 From: Petri Gynther Date: Thu, 24 Mar 2016 11:27:21 -0700 Subject: net: bcmgenet: fix skb_len in bcmgenet_xmit_single() skb_len needs to be skb_headlen(skb) in bcmgenet_xmit_single(). Fragmented skbs can have only Ethernet + IP + TCP headers (14+20+20=54 bytes) in the linear buffer, followed by the rest in fragments. Bumping skb_len to ETH_ZLEN would be incorrect for this case, as it would introduce garbage between TCP header and the fragment data. This also works with regular/non-fragmented small packets < ETH_ZLEN bytes. Successfully tested this on GENETv3 with 42-byte ARP frames. For testing, I used: ethtool -K eth0 tx-checksum-ipv4 off ethtool -K eth0 tx-checksum-ipv6 off echo 0 > /proc/sys/net/ipv4/tcp_timestamps Fixes: 1c1008c793fa ("net: bcmgenet: add main driver file") Signed-off-by: Petri Gynther Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index c1c7c0e6fb7c..cf6445d148ca 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -1297,7 +1297,7 @@ static int bcmgenet_xmit_single(struct net_device *dev, tx_cb_ptr->skb = skb; - skb_len = skb_headlen(skb) < ETH_ZLEN ? ETH_ZLEN : skb_headlen(skb); + skb_len = skb_headlen(skb); mapping = dma_map_single(kdev, skb->data, skb_len, DMA_TO_DEVICE); ret = dma_mapping_error(kdev, mapping); -- cgit From 4a8d224c32238bcee05aa554512ea0256b62f1f9 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 25 Mar 2016 12:27:42 +0100 Subject: drm/amd: Beef up ACP Kconfig menu text The current "text" needs a user to use a crystal ball in order to find out what this ACP thing is. Use the text from a8fe58cec351 ("drm/amd: add ACP driver support") to make it a bit more understandable to the rest of the world. Signed-off-by: Borislav Petkov Cc: Alex Deucher Cc: Chunming Zhou Cc: Jammy Zhou Cc: Maruthi Bayyavarapu Cc: Murali Krishna Vemuri Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/acp/Kconfig | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/acp/Kconfig b/drivers/gpu/drm/amd/acp/Kconfig index 0f734ee05274..ca77ec10147c 100644 --- a/drivers/gpu/drm/amd/acp/Kconfig +++ b/drivers/gpu/drm/amd/acp/Kconfig @@ -1,10 +1,14 @@ -menu "ACP Configuration" +menu "ACP (Audio CoProcessor) Configuration" config DRM_AMD_ACP - bool "Enable ACP IP support" + bool "Enable AMD Audio CoProcessor IP support" select MFD_CORE select PM_GENERIC_DOMAINS if PM help Choose this option to enable ACP IP support for AMD SOCs. + This adds the ACP (Audio CoProcessor) IP driver and wires + it up into the amdgpu driver. The ACP block provides the DMA + engine for the i2s-based ALSA driver. It is required for audio + on APUs which utilize an i2s codec. endmenu -- cgit From f971f2263deaa4a441e377b385c11aee0f3b3f9a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 25 Mar 2016 10:31:04 -0400 Subject: drm/radeon: add a dpm quirk for sapphire Dual-X R7 370 2G D5 bug: https://bugs.freedesktop.org/show_bug.cgi?id=94692 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/si_dpm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index cb75ab72098a..d153b09ac880 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -2926,6 +2926,7 @@ static struct si_dpm_quirk si_dpm_quirk_list[] = { /* PITCAIRN - https://bugs.freedesktop.org/show_bug.cgi?id=76490 */ { PCI_VENDOR_ID_ATI, 0x6810, 0x1462, 0x3036, 0, 120000 }, { PCI_VENDOR_ID_ATI, 0x6811, 0x174b, 0xe271, 0, 120000 }, + { PCI_VENDOR_ID_ATI, 0x6811, 0x174b, 0x2015, 0, 120000 }, { PCI_VENDOR_ID_ATI, 0x6810, 0x174b, 0xe271, 85000, 90000 }, { PCI_VENDOR_ID_ATI, 0x6811, 0x1462, 0x2015, 0, 120000 }, { PCI_VENDOR_ID_ATI, 0x6811, 0x1043, 0x2015, 0, 120000 }, -- cgit From 4cef191d05871fbc8bb3b812880e1997e855a3b9 Mon Sep 17 00:00:00 2001 From: Jaedon Shin Date: Fri, 25 Mar 2016 12:46:54 +0900 Subject: net: phy: bcm7xxx: Add entries for Broadcom BCM7346 and BCM7362 Add PHY entries for the Broadcom BCM7346 and BCM7362 chips, these are 40nm generation Ethernet PHY. Fixes: 815717d1473e ("net: phy: bcm7xxx: Remove wildcard entries") Signed-off-by: Jaedon Shin Signed-off-by: David S. Miller --- drivers/net/phy/bcm7xxx.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c index b881a7b1e4f6..9636da0b6efc 100644 --- a/drivers/net/phy/bcm7xxx.c +++ b/drivers/net/phy/bcm7xxx.c @@ -339,6 +339,8 @@ static struct phy_driver bcm7xxx_driver[] = { BCM7XXX_28NM_GPHY(PHY_ID_BCM7439, "Broadcom BCM7439"), BCM7XXX_28NM_GPHY(PHY_ID_BCM7439_2, "Broadcom BCM7439 (2)"), BCM7XXX_28NM_GPHY(PHY_ID_BCM7445, "Broadcom BCM7445"), + BCM7XXX_40NM_EPHY(PHY_ID_BCM7346, "Broadcom BCM7346"), + BCM7XXX_40NM_EPHY(PHY_ID_BCM7362, "Broadcom BCM7362"), BCM7XXX_40NM_EPHY(PHY_ID_BCM7425, "Broadcom BCM7425"), BCM7XXX_40NM_EPHY(PHY_ID_BCM7429, "Broadcom BCM7429"), BCM7XXX_40NM_EPHY(PHY_ID_BCM7435, "Broadcom BCM7435"), @@ -348,6 +350,8 @@ static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = { { PHY_ID_BCM7250, 0xfffffff0, }, { PHY_ID_BCM7364, 0xfffffff0, }, { PHY_ID_BCM7366, 0xfffffff0, }, + { PHY_ID_BCM7346, 0xfffffff0, }, + { PHY_ID_BCM7362, 0xfffffff0, }, { PHY_ID_BCM7425, 0xfffffff0, }, { PHY_ID_BCM7429, 0xfffffff0, }, { PHY_ID_BCM7439, 0xfffffff0, }, -- cgit From d31fecd1af991e39cbe27a59f290cdcefb7ba6ae Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Fri, 25 Mar 2016 07:14:09 -0400 Subject: qlge: Update version to 1.00.00.35 Just updating version as many fixes got accumulated over 1.00.00.34 Signed-off-by: Manish Chopra Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlge/qlge.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qlge/qlge.h b/drivers/net/ethernet/qlogic/qlge/qlge.h index ef332708e5f2..6d31f92ef2b6 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge.h +++ b/drivers/net/ethernet/qlogic/qlge/qlge.h @@ -18,7 +18,7 @@ */ #define DRV_NAME "qlge" #define DRV_STRING "QLogic 10 Gigabit PCI-E Ethernet Driver " -#define DRV_VERSION "1.00.00.34" +#define DRV_VERSION "1.00.00.35" #define WQ_ADDR_ALIGN 0x3 /* 4 byte alignment */ -- cgit From 9ba723b081a2d1be81fb6f60f912bd94fa744965 Mon Sep 17 00:00:00 2001 From: Cyrille Pitchen Date: Fri, 25 Mar 2016 10:37:34 +0100 Subject: net: macb: remove BUG_ON() and reset the queue to handle RX errors This patch removes two BUG_ON() used to notify about RX queue corruptions on macb (not gem) hardware without actually handling the error. The new code skips corrupted frames but still processes faultless frames. Then it resets the RX queue before restarting the reception from a clean state. This patch is a rework of an older patch proposed by Neil Armstrong: http://patchwork.ozlabs.org/patch/371525/ Signed-off-by: Cyrille Pitchen Acked-by: Neil Armstrong Acked-by: Nicolas Ferre Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 59 ++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index f715352a9b85..6c3dc27cb100 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -917,7 +917,10 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag, unsigned int frag_len = bp->rx_buffer_size; if (offset + frag_len > len) { - BUG_ON(frag != last_frag); + if (unlikely(frag != last_frag)) { + dev_kfree_skb_any(skb); + return -1; + } frag_len = len - offset; } skb_copy_to_linear_data_offset(skb, offset, @@ -945,8 +948,23 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag, return 0; } +static inline void macb_init_rx_ring(struct macb *bp) +{ + dma_addr_t addr; + int i; + + addr = bp->rx_buffers_dma; + for (i = 0; i < RX_RING_SIZE; i++) { + bp->rx_ring[i].addr = addr; + bp->rx_ring[i].ctrl = 0; + addr += bp->rx_buffer_size; + } + bp->rx_ring[RX_RING_SIZE - 1].addr |= MACB_BIT(RX_WRAP); +} + static int macb_rx(struct macb *bp, int budget) { + bool reset_rx_queue = false; int received = 0; unsigned int tail; int first_frag = -1; @@ -972,10 +990,18 @@ static int macb_rx(struct macb *bp, int budget) if (ctrl & MACB_BIT(RX_EOF)) { int dropped; - BUG_ON(first_frag == -1); + + if (unlikely(first_frag == -1)) { + reset_rx_queue = true; + continue; + } dropped = macb_rx_frame(bp, first_frag, tail); first_frag = -1; + if (unlikely(dropped < 0)) { + reset_rx_queue = true; + continue; + } if (!dropped) { received++; budget--; @@ -983,6 +1009,26 @@ static int macb_rx(struct macb *bp, int budget) } } + if (unlikely(reset_rx_queue)) { + unsigned long flags; + u32 ctrl; + + netdev_err(bp->dev, "RX queue corruption: reset it\n"); + + spin_lock_irqsave(&bp->lock, flags); + + ctrl = macb_readl(bp, NCR); + macb_writel(bp, NCR, ctrl & ~MACB_BIT(RE)); + + macb_init_rx_ring(bp); + macb_writel(bp, RBQP, bp->rx_ring_dma); + + macb_writel(bp, NCR, ctrl | MACB_BIT(RE)); + + spin_unlock_irqrestore(&bp->lock, flags); + return received; + } + if (first_frag != -1) bp->rx_tail = first_frag; else @@ -1523,15 +1569,8 @@ static void gem_init_rings(struct macb *bp) static void macb_init_rings(struct macb *bp) { int i; - dma_addr_t addr; - addr = bp->rx_buffers_dma; - for (i = 0; i < RX_RING_SIZE; i++) { - bp->rx_ring[i].addr = addr; - bp->rx_ring[i].ctrl = 0; - addr += bp->rx_buffer_size; - } - bp->rx_ring[RX_RING_SIZE - 1].addr |= MACB_BIT(RX_WRAP); + macb_init_rx_ring(bp); for (i = 0; i < TX_RING_SIZE; i++) { bp->queues[0].tx_ring[i].addr = 0; -- cgit From a21211672c9a1d730a39aa65d4a5b3414700adfb Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 23 Mar 2016 21:07:39 -0700 Subject: ACPI / processor: Request native thermal interrupt handling via _OSC There are several reports of freeze on enabling HWP (Hardware PStates) feature on Skylake-based systems by the Intel P-states driver. The root cause is identified as the HWP interrupts causing BIOS code to freeze. HWP interrupts use the thermal LVT which can be handled by Linux natively, but on the affected Skylake-based systems SMM will respond to it by default. This is a problem for several reasons: - On the affected systems the SMM thermal LVT handler is broken (it will crash when invoked) and a BIOS update is necessary to fix it. - With thermal interrupt handled in SMM we lose all of the reporting features of the arch/x86/kernel/cpu/mcheck/therm_throt driver. - Some thermal drivers like x86-package-temp depend on the thermal threshold interrupts signaled via the thermal LVT. - The HWP interrupts are useful for debugging and tuning performance (if the kernel can handle them). The native handling of thermal interrupts needs to be enabled because of that. This requires some way to tell SMM that the OS can handle thermal interrupts. That can be done by using _OSC/_PDC in processor scope very early during ACPI initialization. The meaning of _OSC/_PDC bit 12 in processor scope is whether or not the OS supports native handling of interrupts for Collaborative Processor Performance Control (CPPC) notifications. Since on HWP-capable systems CPPC is a firmware interface to HWP, setting this bit effectively tells the firmware that the OS will handle thermal interrupts natively going forward. For details on _OSC/_PDC refer to: http://www.intel.com/content/www/us/en/standards/processor-vendor-specific-acpi-specification.html To implement the _OSC/_PDC handshake as described, introduce a new function, acpi_early_processor_osc(), that walks the ACPI namespace looking for ACPI processor objects and invokes _OSC for them with bit 12 in the capabilities buffer set and terminates the namespace walk on the first success. Also modify intel_thermal_interrupt() to clear HWP status bits in the HWP_STATUS MSR to acknowledge HWP interrupts (which prevents them from firing continuously). Signed-off-by: Srinivas Pandruvada [ rjw: Subject & changelog, function rename ] Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_processor.c | 52 +++++++++++++++++++++++++++++++++++++++++++ drivers/acpi/bus.c | 3 +++ drivers/acpi/internal.h | 6 +++++ 3 files changed, 61 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index b5e54f2da53d..0d92d0f915e9 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -491,6 +491,58 @@ static void acpi_processor_remove(struct acpi_device *device) } #endif /* CONFIG_ACPI_HOTPLUG_CPU */ +#ifdef CONFIG_X86 +static bool acpi_hwp_native_thermal_lvt_set; +static acpi_status __init acpi_hwp_native_thermal_lvt_osc(acpi_handle handle, + u32 lvl, + void *context, + void **rv) +{ + u8 sb_uuid_str[] = "4077A616-290C-47BE-9EBD-D87058713953"; + u32 capbuf[2]; + struct acpi_osc_context osc_context = { + .uuid_str = sb_uuid_str, + .rev = 1, + .cap.length = 8, + .cap.pointer = capbuf, + }; + + if (acpi_hwp_native_thermal_lvt_set) + return AE_CTRL_TERMINATE; + + capbuf[0] = 0x0000; + capbuf[1] = 0x1000; /* set bit 12 */ + + if (ACPI_SUCCESS(acpi_run_osc(handle, &osc_context))) { + if (osc_context.ret.pointer && osc_context.ret.length > 1) { + u32 *capbuf_ret = osc_context.ret.pointer; + + if (capbuf_ret[1] & 0x1000) { + acpi_handle_info(handle, + "_OSC native thermal LVT Acked\n"); + acpi_hwp_native_thermal_lvt_set = true; + } + } + kfree(osc_context.ret.pointer); + } + + return AE_OK; +} + +void __init acpi_early_processor_osc(void) +{ + if (boot_cpu_has(X86_FEATURE_HWP)) { + acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, + acpi_hwp_native_thermal_lvt_osc, + NULL, NULL, NULL); + acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, + acpi_hwp_native_thermal_lvt_osc, + NULL, NULL); + } +} +#endif + /* * The following ACPI IDs are known to be suitable for representing as * processor devices. diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 891c42d1cd65..f9081b791b81 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -1005,6 +1005,9 @@ static int __init acpi_bus_init(void) goto error1; } + /* Set capability bits for _OSC under processor scope */ + acpi_early_processor_osc(); + /* * _OSC method may exist in module level code, * so it must be run after ACPI_FULL_INITIALIZATION diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 1e6833a5cd44..6f41c73f82bb 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -138,6 +138,12 @@ void acpi_early_processor_set_pdc(void); static inline void acpi_early_processor_set_pdc(void) {} #endif +#ifdef CONFIG_X86 +void acpi_early_processor_osc(void); +#else +static inline void acpi_early_processor_osc(void) {} +#endif + /* -------------------------------------------------------------------------- Embedded Controller -------------------------------------------------------------------------- */ -- cgit From 3c2e2266a5bd2d1cef258e6e54dca1d99946379f Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 26 Mar 2016 12:28:05 -0700 Subject: hwmon: (max1111) Return -ENODEV from max1111_read_channel if not instantiated arm:pxa_defconfig can result in the following crash if the max1111 driver is not instantiated. Unhandled fault: page domain fault (0x01b) at 0x00000000 pgd = c0004000 [00000000] *pgd=00000000 Internal error: : 1b [#1] PREEMPT ARM Modules linked in: CPU: 0 PID: 300 Comm: kworker/0:1 Not tainted 4.5.0-01301-g1701f680407c #10 Hardware name: SHARP Akita Workqueue: events sharpsl_charge_toggle task: c390a000 ti: c391e000 task.ti: c391e000 PC is at max1111_read_channel+0x20/0x30 LR is at sharpsl_pm_pxa_read_max1111+0x2c/0x3c pc : [] lr : [] psr: 20000013 ... [] (max1111_read_channel) from [] (sharpsl_pm_pxa_read_max1111+0x2c/0x3c) [] (sharpsl_pm_pxa_read_max1111) from [] (spitzpm_read_devdata+0x5c/0xc4) [] (spitzpm_read_devdata) from [] (sharpsl_check_battery_temp+0x78/0x110) [] (sharpsl_check_battery_temp) from [] (sharpsl_charge_toggle+0x48/0x110) [] (sharpsl_charge_toggle) from [] (process_one_work+0x14c/0x48c) [] (process_one_work) from [] (worker_thread+0x3c/0x5d4) [] (worker_thread) from [] (kthread+0xd0/0xec) [] (kthread) from [] (ret_from_fork+0x14/0x24) This can occur because the SPI controller driver (SPI_PXA2XX) is built as module and thus not necessarily loaded. While building SPI_PXA2XX into the kernel would make the problem disappear, it appears prudent to ensure that the driver is instantiated before accessing its data structures. Cc: Arnd Bergmann Cc: stable@vger.kernel.org Signed-off-by: Guenter Roeck --- drivers/hwmon/max1111.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/hwmon/max1111.c b/drivers/hwmon/max1111.c index 36544c4f653c..303d0c9df907 100644 --- a/drivers/hwmon/max1111.c +++ b/drivers/hwmon/max1111.c @@ -85,6 +85,9 @@ static struct max1111_data *the_max1111; int max1111_read_channel(int channel) { + if (!the_max1111 || !the_max1111->spi) + return -ENODEV; + return max1111_read(&the_max1111->spi->dev, channel); } EXPORT_SYMBOL(max1111_read_channel); @@ -258,6 +261,9 @@ static int max1111_remove(struct spi_device *spi) { struct max1111_data *data = spi_get_drvdata(spi); +#ifdef CONFIG_SHARPSL_PM + the_max1111 = NULL; +#endif hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&spi->dev.kobj, &max1110_attr_group); sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group); -- cgit From a69f0e281d9eb08eb277be051f920ea863e258e2 Mon Sep 17 00:00:00 2001 From: Diego Viola Date: Sun, 27 Mar 2016 20:58:15 -0300 Subject: drivers/net/usb/plusb.c: Fix typo Signed-off-by: Diego Viola Signed-off-by: David S. Miller --- drivers/net/usb/plusb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/usb/plusb.c b/drivers/net/usb/plusb.c index 1bfe0fcaccf5..22e1a9a99a7d 100644 --- a/drivers/net/usb/plusb.c +++ b/drivers/net/usb/plusb.c @@ -38,7 +38,7 @@ * HEADS UP: this handshaking isn't all that robust. This driver * gets confused easily if you unplug one end of the cable then * try to connect it again; you'll need to restart both ends. The - * "naplink" software (used by some PlayStation/2 deveopers) does + * "naplink" software (used by some PlayStation/2 developers) does * the handshaking much better! Also, sometimes this hardware * seems to get wedged under load. Prolific docs are weak, and * don't identify differences between PL2301 and PL2302, much less -- cgit From 66391b383b70920629df403f2881ea48805e6659 Mon Sep 17 00:00:00 2001 From: Cosmin-Gabriel Samoila Date: Sat, 26 Mar 2016 02:49:50 +0200 Subject: Drivers: isdn: hisax: isac.c: Fix assignment and check into one expression. Fix variable assignment inside if statement. It is error-prone and hard to read. Signed-off-by: Cosmin-Gabriel Samoila Signed-off-by: David S. Miller --- drivers/isdn/hisax/isac.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c index 7fdf78f46433..df7e05ca8f9c 100644 --- a/drivers/isdn/hisax/isac.c +++ b/drivers/isdn/hisax/isac.c @@ -215,9 +215,11 @@ isac_interrupt(struct IsdnCardState *cs, u_char val) if (count == 0) count = 32; isac_empty_fifo(cs, count); - if ((count = cs->rcvidx) > 0) { + count = cs->rcvidx; + if (count > 0) { cs->rcvidx = 0; - if (!(skb = alloc_skb(count, GFP_ATOMIC))) + skb = alloc_skb(count, GFP_ATOMIC); + if (!skb) printk(KERN_WARNING "HiSax: D receive out of memory\n"); else { memcpy(skb_put(skb, count), cs->rcvbuf, count); @@ -251,7 +253,8 @@ isac_interrupt(struct IsdnCardState *cs, u_char val) cs->tx_skb = NULL; } } - if ((cs->tx_skb = skb_dequeue(&cs->sq))) { + cs->tx_skb = skb_dequeue(&cs->sq); + if (cs->tx_skb) { cs->tx_cnt = 0; isac_fill_fifo(cs); } else @@ -313,7 +316,8 @@ afterXPR: #if ARCOFI_USE if (v1 & 0x08) { if (!cs->dc.isac.mon_rx) { - if (!(cs->dc.isac.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) { + cs->dc.isac.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC); + if (!cs->dc.isac.mon_rx) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "ISAC MON RX out of memory!"); cs->dc.isac.mocr &= 0xf0; @@ -343,7 +347,8 @@ afterXPR: afterMONR0: if (v1 & 0x80) { if (!cs->dc.isac.mon_rx) { - if (!(cs->dc.isac.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) { + cs->dc.isac.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC); + if (!cs->dc.isac.mon_rx) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "ISAC MON RX out of memory!"); cs->dc.isac.mocr &= 0x0f; -- cgit From 79c134239df989167acd277364b83ff9e91e70c4 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Sat, 26 Mar 2016 22:24:09 +0100 Subject: net: sxgbe: fix error paths in sxgbe_platform_probe() We need to use post-decrement to ensure that irq_dispose_mapping is also called on priv->rxq[0]->irq_no; moreover, if one of the above for loops failed already at i==0 (so we reach one of these labels with that value of i), we'll enter an essentially infinite loop of out-of-bounds accesses. Signed-off-by: Rasmus Villemoes Reviewed-by: Francois Romieu Signed-off-by: David S. Miller --- drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c index b02eed12bfc5..73427e29df2a 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c @@ -155,11 +155,11 @@ static int sxgbe_platform_probe(struct platform_device *pdev) return 0; err_rx_irq_unmap: - while (--i) + while (i--) irq_dispose_mapping(priv->rxq[i]->irq_no); i = SXGBE_TX_QUEUES; err_tx_irq_unmap: - while (--i) + while (i--) irq_dispose_mapping(priv->txq[i]->irq_no); irq_dispose_mapping(priv->irq); err_drv_remove: -- cgit From d7be81a5916bdb1d904803958e5991a16f7ae4b2 Mon Sep 17 00:00:00 2001 From: Lino Sanfilippo Date: Sun, 27 Mar 2016 12:22:02 +0200 Subject: ravb: fix software timestamping In ravb_start_xmit dont call skb_tx_timestamp only when hardware timestamping is requested: in the latter case software timestamps are suppressed and thus the call of skb_tx_timestamp does not have any effect. Instead call skb_tx_timestamp unconditionally in ravb_start_xmit, since the function checks itself if software timestamping is required or should be skipped due to hardware timestamping. Signed-off-by: Lino Sanfilippo Acked-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/ravb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index 4e1a7dba7c4a..087e14a3fba7 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -1377,11 +1377,11 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev) /* TAG and timestamp required flag */ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; - skb_tx_timestamp(skb); desc->tagh_tsr = (ts_skb->tag >> 4) | TX_TSR; desc->ds_tagl |= le16_to_cpu(ts_skb->tag << 12); } + skb_tx_timestamp(skb); /* Descriptor type must be set after all the above writes */ dma_wmb(); desc->die_dt = DT_FEND; -- cgit From 92915da647be831ddbaa7e03e7528d921ec7f8aa Mon Sep 17 00:00:00 2001 From: John Keeping Date: Fri, 4 Mar 2016 11:04:03 +0000 Subject: drm/rockchip: vop: fix crtc size in plane check If the geometry of a crtc is changing in an atomic update then we must validate the plane size against the new state of the crtc and not the current size, otherwise if the crtc size is increasing the plane will be cropped at the previous size and will not fill the screen. Signed-off-by: John Keeping --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index fd370548d7d7..82d55bd8deb6 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -549,6 +549,7 @@ static int vop_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) { struct drm_crtc *crtc = state->crtc; + struct drm_crtc_state *crtc_state; struct drm_framebuffer *fb = state->fb; struct vop_win *vop_win = to_vop_win(plane); struct vop_plane_state *vop_plane_state = to_vop_plane_state(state); @@ -563,12 +564,13 @@ static int vop_plane_atomic_check(struct drm_plane *plane, int max_scale = win->phy->scl ? FRAC_16_16(8, 1) : DRM_PLANE_HELPER_NO_SCALING; - crtc = crtc ? crtc : plane->state->crtc; - /* - * Both crtc or plane->state->crtc can be null. - */ if (!crtc || !fb) goto out_disable; + + crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc); + if (WARN_ON(!crtc_state)) + return -EINVAL; + src->x1 = state->src_x; src->y1 = state->src_y; src->x2 = state->src_x + state->src_w; @@ -580,8 +582,8 @@ static int vop_plane_atomic_check(struct drm_plane *plane, clip.x1 = 0; clip.y1 = 0; - clip.x2 = crtc->mode.hdisplay; - clip.y2 = crtc->mode.vdisplay; + clip.x2 = crtc_state->adjusted_mode.hdisplay; + clip.y2 = crtc_state->adjusted_mode.vdisplay; ret = drm_plane_helper_check_update(plane, crtc, state->fb, src, dest, &clip, -- cgit From f135046e519dc54a701110fa93a6d61c4989ed96 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Fri, 11 Mar 2016 17:21:17 +0000 Subject: drm/rockchip: cancel pending vblanks on close When closing the DRM device while a vblank is pending, we access file_priv after it has been free'd, which gives: Unable to handle kernel NULL pointer dereference at virtual address 00000000 ... PC is at __list_add+0x5c/0xe8 LR is at send_vblank_event+0x54/0x1f0 ... [] (__list_add) from [] (send_vblank_event+0x54/0x1f0) [] (send_vblank_event) from [] (drm_send_vblank_event+0x70/0x78) [] (drm_send_vblank_event) from [] (drm_crtc_send_vblank_event+0x30/0x34) [] (drm_crtc_send_vblank_event) from [] (vop_isr+0x224/0x28c) [] (vop_isr) from [] (handle_irq_event_percpu+0x12c/0x3e4) This can be triggered somewhat reliably with: modetest -M rockchip -v -s ... Add a preclose hook to the driver so that we can discard any pending vblank events when the device is closed. Signed-off-by: John Keeping --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 22 ++++++++++++++++++++++ drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 1 + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 20 ++++++++++++++++++++ 3 files changed, 43 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 896da09e49ee..f556a8f4fde6 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -251,6 +251,27 @@ static int rockchip_drm_unload(struct drm_device *drm_dev) return 0; } +static void rockchip_drm_crtc_cancel_pending_vblank(struct drm_crtc *crtc, + struct drm_file *file_priv) +{ + struct rockchip_drm_private *priv = crtc->dev->dev_private; + int pipe = drm_crtc_index(crtc); + + if (pipe < ROCKCHIP_MAX_CRTC && + priv->crtc_funcs[pipe] && + priv->crtc_funcs[pipe]->cancel_pending_vblank) + priv->crtc_funcs[pipe]->cancel_pending_vblank(crtc, file_priv); +} + +static void rockchip_drm_preclose(struct drm_device *dev, + struct drm_file *file_priv) +{ + struct drm_crtc *crtc; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) + rockchip_drm_crtc_cancel_pending_vblank(crtc, file_priv); +} + void rockchip_drm_lastclose(struct drm_device *dev) { struct rockchip_drm_private *priv = dev->dev_private; @@ -281,6 +302,7 @@ static struct drm_driver rockchip_drm_driver = { DRIVER_PRIME | DRIVER_ATOMIC, .load = rockchip_drm_load, .unload = rockchip_drm_unload, + .preclose = rockchip_drm_preclose, .lastclose = rockchip_drm_lastclose, .get_vblank_counter = drm_vblank_no_hw_counter, .enable_vblank = rockchip_drm_crtc_enable_vblank, diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index 3529f692edb8..00d17d71aa4c 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -40,6 +40,7 @@ struct rockchip_crtc_funcs { int (*enable_vblank)(struct drm_crtc *crtc); void (*disable_vblank)(struct drm_crtc *crtc); void (*wait_for_update)(struct drm_crtc *crtc); + void (*cancel_pending_vblank)(struct drm_crtc *crtc, struct drm_file *file_priv); }; struct rockchip_atomic_commit { diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 82d55bd8deb6..44b2ba7b5cc9 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -875,10 +875,30 @@ static void vop_crtc_wait_for_update(struct drm_crtc *crtc) WARN_ON(!wait_for_completion_timeout(&vop->wait_update_complete, 100)); } +static void vop_crtc_cancel_pending_vblank(struct drm_crtc *crtc, + struct drm_file *file_priv) +{ + struct drm_device *drm = crtc->dev; + struct vop *vop = to_vop(crtc); + struct drm_pending_vblank_event *e; + unsigned long flags; + + spin_lock_irqsave(&drm->event_lock, flags); + e = vop->event; + if (e && e->base.file_priv == file_priv) { + vop->event = NULL; + + e->base.destroy(&e->base); + file_priv->event_space += sizeof(e->event); + } + spin_unlock_irqrestore(&drm->event_lock, flags); +} + static const struct rockchip_crtc_funcs private_crtc_funcs = { .enable_vblank = vop_crtc_enable_vblank, .disable_vblank = vop_crtc_disable_vblank, .wait_for_update = vop_crtc_wait_for_update, + .cancel_pending_vblank = vop_crtc_cancel_pending_vblank, }; static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, -- cgit From eac5ad8861639754a3976bfa1581a73e772624c6 Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Fri, 18 Mar 2016 12:22:02 +0100 Subject: drm/rockchip: vop: Don't reject empty modesets So that when DRM_IOCTL_MODE_SETCRTC is called without a FB nor mode, the CRTC gets disabled. Signed-off-by: Tomeu Vizoso Link: http://lkml.kernel.org/g/CAAObsKAv+05ih5U+=4kic_NsjGMhfxYheHR8xXXmacZs+p5SHw@mail.gmail.com --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 44b2ba7b5cc9..c01a380e3bb9 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -907,9 +907,6 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, { struct vop *vop = to_vop(crtc); - if (adjusted_mode->htotal == 0 || adjusted_mode->vtotal == 0) - return false; - adjusted_mode->clock = clk_round_rate(vop->dclk, mode->clock * 1000) / 1000; -- cgit From 3ed6c64911f2335b271c21363b7834072fc03303 Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Tue, 22 Mar 2016 16:08:04 +0100 Subject: drm/rockchip: vop: Disable planes when disabling CRTC When a VOP is re-enabled, it will start scanning right away the framebuffers that were configured from the last time, even if those have been destroyed already. To prevent the VOP from trying to access freed memory, disable all its windows when the CRTC is being disabled, then each window will get a valid framebuffer address before it's enabled again. Signed-off-by: Tomeu Vizoso Link: http://lkml.kernel.org/g/CAAObsKAv+05ih5U+=4kic_NsjGMhfxYheHR8xXXmacZs+p5SHw@mail.gmail.com --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index c01a380e3bb9..12854ac9d542 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -499,10 +499,25 @@ err_disable_hclk: static void vop_crtc_disable(struct drm_crtc *crtc) { struct vop *vop = to_vop(crtc); + int i; if (!vop->is_enabled) return; + /* + * We need to make sure that all windows are disabled before we + * disable that crtc. Otherwise we might try to scan from a destroyed + * buffer later. + */ + for (i = 0; i < vop->data->win_size; i++) { + struct vop_win *vop_win = &vop->win[i]; + const struct vop_win_data *win = vop_win->data; + + spin_lock(&vop->reg_lock); + VOP_WIN_SET(vop, win, enable, 0); + spin_unlock(&vop->reg_lock); + } + drm_crtc_vblank_off(crtc); /* -- cgit From 948cf42700b15fc65ec4cc3ac52a8bbeb84b87ef Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Mon, 7 Mar 2016 14:00:50 -0800 Subject: drm/rockchip: dw_hdmi: Call drm_encoder_cleanup() in error path The drm_encoder_cleanup() was missing both from the error path of dw_hdmi_rockchip_bind(). This caused a crash when slub_debug was enabled and we ended up deferring probe of HDMI at boot. This call isn't needed from unbind() because if dw_hdmi_bind() returns no error then it takes over the job of freeing the encoder (in dw_hdmi_unbind). Signed-off-by: Douglas Anderson --- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index 3d3cf2f8891e..88776aba984e 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -293,7 +293,16 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs, DRM_MODE_ENCODER_TMDS, NULL); - return dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data); + ret = dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data); + + /* + * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(), + * which would have called the encoder cleanup. Do it manually. + */ + if (ret) + drm_encoder_cleanup(encoder); + + return ret; } static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master, -- cgit From 328b51c0f5a07f3ee891ff012eb7f454be9d17c0 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Mon, 7 Mar 2016 14:00:52 -0800 Subject: drm/rockchip: vop: Fix vop crtc cleanup This fixes a few problems in the vop crtc cleanup (handling error paths and cleanup upon exit): * The vop_create_crtc() error path had an unsafe version of the iterator used for iterating over all planes (though it was destroying planes in the iterator so should have used the safe version) * vop_destroy_crtc() - wasn't calling vop_plane_destroy(), which made slub_debug unhappy, at least if we ended up running this due to a deferred probe. * In vop_create_crtc() if we were missing the "port" device tree node we would fail but not return an error (found by code inspection). Fix these problems. Signed-off-by: Douglas Anderson --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 12854ac9d542..a619f120f801 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -1142,7 +1142,7 @@ static int vop_create_crtc(struct vop *vop) const struct vop_data *vop_data = vop->data; struct device *dev = vop->dev; struct drm_device *drm_dev = vop->drm_dev; - struct drm_plane *primary = NULL, *cursor = NULL, *plane; + struct drm_plane *primary = NULL, *cursor = NULL, *plane, *tmp; struct drm_crtc *crtc = &vop->crtc; struct device_node *port; int ret; @@ -1182,7 +1182,7 @@ static int vop_create_crtc(struct vop *vop) ret = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor, &vop_crtc_funcs, NULL); if (ret) - return ret; + goto err_cleanup_planes; drm_crtc_helper_add(crtc, &vop_crtc_helper_funcs); @@ -1215,6 +1215,7 @@ static int vop_create_crtc(struct vop *vop) if (!port) { DRM_ERROR("no port node found in %s\n", dev->of_node->full_name); + ret = -ENOENT; goto err_cleanup_crtc; } @@ -1228,7 +1229,8 @@ static int vop_create_crtc(struct vop *vop) err_cleanup_crtc: drm_crtc_cleanup(crtc); err_cleanup_planes: - list_for_each_entry(plane, &drm_dev->mode_config.plane_list, head) + list_for_each_entry_safe(plane, tmp, &drm_dev->mode_config.plane_list, + head) drm_plane_cleanup(plane); return ret; } @@ -1236,9 +1238,28 @@ err_cleanup_planes: static void vop_destroy_crtc(struct vop *vop) { struct drm_crtc *crtc = &vop->crtc; + struct drm_device *drm_dev = vop->drm_dev; + struct drm_plane *plane, *tmp; rockchip_unregister_crtc_funcs(crtc); of_node_put(crtc->port); + + /* + * We need to cleanup the planes now. Why? + * + * The planes are "&vop->win[i].base". That means the memory is + * all part of the big "struct vop" chunk of memory. That memory + * was devm allocated and associated with this component. We need to + * free it ourselves before vop_unbind() finishes. + */ + list_for_each_entry_safe(plane, tmp, &drm_dev->mode_config.plane_list, + head) + vop_plane_destroy(plane); + + /* + * Destroy CRTC after vop_plane_destroy() since vop_disable_plane() + * references the CRTC. + */ drm_crtc_cleanup(crtc); } -- cgit From 06b898ec84139b9d5957ec0e275fa0a6a1825df3 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Mon, 7 Mar 2016 14:00:53 -0800 Subject: drm/rockchip: dw_hdmi: Don't call platform_set_drvdata() The Rockchip dw_hdmi driver just called platform_set_drvdata() to get your hopes up that maybe, somehow, you'd be able to retrieve the 'struct rockchip_hdmi' from a pointer to the 'struct device'. You can't. When we call dw_hdmi_bind() the main driver calls dev_set_drvdata(), which clobbers our setting. Let's just remove the platform_set_drvdata() to avoid dashing people's hopes. Signed-off-by: Douglas Anderson --- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index 88776aba984e..d5cfef75fc80 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -271,8 +271,6 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, if (!iores) return -ENXIO; - platform_set_drvdata(pdev, hdmi); - encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node); /* * If we failed to find the CRTC(s) which this encoder is -- cgit From a64663d9870364bd2a2df62bf0d3a9fbe5ea62a8 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 28 Mar 2016 10:16:40 -0400 Subject: drm/radeon: add another R7 370 quirk bug: https://bugzilla.kernel.org/show_bug.cgi?id=115291 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/si_dpm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index d153b09ac880..a280a3201832 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -2930,6 +2930,7 @@ static struct si_dpm_quirk si_dpm_quirk_list[] = { { PCI_VENDOR_ID_ATI, 0x6810, 0x174b, 0xe271, 85000, 90000 }, { PCI_VENDOR_ID_ATI, 0x6811, 0x1462, 0x2015, 0, 120000 }, { PCI_VENDOR_ID_ATI, 0x6811, 0x1043, 0x2015, 0, 120000 }, + { PCI_VENDOR_ID_ATI, 0x6811, 0x148c, 0x2015, 0, 120000 }, { 0, 0, 0, 0 }, }; -- cgit From 0e5585dc870af947fab2af96a88c2d8b4270247c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 28 Mar 2016 10:21:20 -0400 Subject: drm/radeon: add a dpm quirk for all R7 370 parts Higher mclk values are not stable due to a bug somewhere. Limit them for now. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/si_dpm.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index a280a3201832..af4df81c4e0c 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -3010,6 +3010,10 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, } ++p; } + /* limit mclk on all R7 370 parts for stability */ + if (rdev->pdev->device == 0x6811 && + rdev->pdev->revision == 0x81) + max_mclk = 120000; if (rps->vce_active) { rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk; -- cgit From 43adc067c5a070a5ef97d0c25e33df19c4481484 Mon Sep 17 00:00:00 2001 From: Lisheng Date: Mon, 28 Mar 2016 18:40:56 +0800 Subject: net: hns: fixed the setting and getting overtime bug The overtime setting and getting REGs in HNS V2 is defferent from HNS V1. It needs to be distinguished between them if getting or setting the REGs. Signed-off-by: Lisheng Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c | 60 +++---- drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c | 196 ++++++++++------------ drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h | 23 +-- drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h | 1 + 4 files changed, 126 insertions(+), 154 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c index 285c893ab135..1dd1d6974d47 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c @@ -159,11 +159,6 @@ struct hnae_handle *hns_ae_get_handle(struct hnae_ae_dev *dev, ae_handle->qs[i]->tx_ring.q = ae_handle->qs[i]; ring_pair_cb->used_by_vf = 1; - if (port_idx < DSAF_SERVICE_PORT_NUM_PER_DSAF) - ring_pair_cb->port_id_in_dsa = port_idx; - else - ring_pair_cb->port_id_in_dsa = 0; - ring_pair_cb++; } @@ -453,59 +448,46 @@ static int hns_ae_set_pauseparam(struct hnae_handle *handle, static void hns_ae_get_coalesce_usecs(struct hnae_handle *handle, u32 *tx_usecs, u32 *rx_usecs) { - int port; - - port = hns_ae_map_eport_to_dport(handle->eport_id); + struct ring_pair_cb *ring_pair = + container_of(handle->qs[0], struct ring_pair_cb, q); - *tx_usecs = hns_rcb_get_coalesce_usecs( - hns_ae_get_dsaf_dev(handle->dev), - hns_dsaf_get_comm_idx_by_port(port)); - *rx_usecs = hns_rcb_get_coalesce_usecs( - hns_ae_get_dsaf_dev(handle->dev), - hns_dsaf_get_comm_idx_by_port(port)); + *tx_usecs = hns_rcb_get_coalesce_usecs(ring_pair->rcb_common, + ring_pair->port_id_in_comm); + *rx_usecs = hns_rcb_get_coalesce_usecs(ring_pair->rcb_common, + ring_pair->port_id_in_comm); } static void hns_ae_get_rx_max_coalesced_frames(struct hnae_handle *handle, u32 *tx_frames, u32 *rx_frames) { - int port; + struct ring_pair_cb *ring_pair = + container_of(handle->qs[0], struct ring_pair_cb, q); - assert(handle); - - port = hns_ae_map_eport_to_dport(handle->eport_id); - - *tx_frames = hns_rcb_get_coalesced_frames( - hns_ae_get_dsaf_dev(handle->dev), port); - *rx_frames = hns_rcb_get_coalesced_frames( - hns_ae_get_dsaf_dev(handle->dev), port); + *tx_frames = hns_rcb_get_coalesced_frames(ring_pair->rcb_common, + ring_pair->port_id_in_comm); + *rx_frames = hns_rcb_get_coalesced_frames(ring_pair->rcb_common, + ring_pair->port_id_in_comm); } static void hns_ae_set_coalesce_usecs(struct hnae_handle *handle, u32 timeout) { - int port; + struct ring_pair_cb *ring_pair = + container_of(handle->qs[0], struct ring_pair_cb, q); - assert(handle); - - port = hns_ae_map_eport_to_dport(handle->eport_id); - - hns_rcb_set_coalesce_usecs(hns_ae_get_dsaf_dev(handle->dev), - port, timeout); + (void)hns_rcb_set_coalesce_usecs( + ring_pair->rcb_common, ring_pair->port_id_in_comm, timeout); } static int hns_ae_set_coalesce_frames(struct hnae_handle *handle, u32 coalesce_frames) { - int port; - int ret; + struct ring_pair_cb *ring_pair = + container_of(handle->qs[0], struct ring_pair_cb, q); - assert(handle); - - port = hns_ae_map_eport_to_dport(handle->eport_id); - - ret = hns_rcb_set_coalesced_frames(hns_ae_get_dsaf_dev(handle->dev), - port, coalesce_frames); - return ret; + return hns_rcb_set_coalesced_frames( + ring_pair->rcb_common, + ring_pair->port_id_in_comm, coalesce_frames); } void hns_ae_update_stats(struct hnae_handle *handle, diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c index 12188807468c..28ee26e5c478 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c @@ -215,9 +215,9 @@ static void hns_rcb_ring_init(struct ring_pair_cb *ring_pair, int ring_type) dsaf_write_dev(q, RCB_RING_RX_RING_BD_LEN_REG, bd_size_type); dsaf_write_dev(q, RCB_RING_RX_RING_BD_NUM_REG, - ring_pair->port_id_in_dsa); + ring_pair->port_id_in_comm); dsaf_write_dev(q, RCB_RING_RX_RING_PKTLINE_REG, - ring_pair->port_id_in_dsa); + ring_pair->port_id_in_comm); } else { dsaf_write_dev(q, RCB_RING_TX_RING_BASEADDR_L_REG, (u32)dma); @@ -227,9 +227,9 @@ static void hns_rcb_ring_init(struct ring_pair_cb *ring_pair, int ring_type) dsaf_write_dev(q, RCB_RING_TX_RING_BD_LEN_REG, bd_size_type); dsaf_write_dev(q, RCB_RING_TX_RING_BD_NUM_REG, - ring_pair->port_id_in_dsa); + ring_pair->port_id_in_comm); dsaf_write_dev(q, RCB_RING_TX_RING_PKTLINE_REG, - ring_pair->port_id_in_dsa); + ring_pair->port_id_in_comm); } } @@ -256,50 +256,16 @@ static void hns_rcb_set_port_desc_cnt(struct rcb_common_cb *rcb_common, desc_cnt); } -/** - *hns_rcb_set_port_coalesced_frames - set rcb port coalesced frames - *@rcb_common: rcb_common device - *@port_idx:port index - *@coalesced_frames:BD num for coalesced frames - */ -static int hns_rcb_set_port_coalesced_frames(struct rcb_common_cb *rcb_common, - u32 port_idx, - u32 coalesced_frames) -{ - if (coalesced_frames >= rcb_common->desc_num || - coalesced_frames > HNS_RCB_MAX_COALESCED_FRAMES) - return -EINVAL; - - dsaf_write_dev(rcb_common, RCB_CFG_PKTLINE_REG + port_idx * 4, - coalesced_frames); - return 0; -} - -/** - *hns_rcb_get_port_coalesced_frames - set rcb port coalesced frames - *@rcb_common: rcb_common device - *@port_idx:port index - * return coaleseced frames value - */ -static u32 hns_rcb_get_port_coalesced_frames(struct rcb_common_cb *rcb_common, - u32 port_idx) +static void hns_rcb_set_port_timeout( + struct rcb_common_cb *rcb_common, u32 port_idx, u32 timeout) { - if (port_idx >= HNS_RCB_SERVICE_NW_ENGINE_NUM) - port_idx = 0; - - return dsaf_read_dev(rcb_common, - RCB_CFG_PKTLINE_REG + port_idx * 4); -} - -/** - *hns_rcb_set_timeout - set rcb port coalesced time_out - *@rcb_common: rcb_common device - *@time_out:time for coalesced time_out - */ -static void hns_rcb_set_timeout(struct rcb_common_cb *rcb_common, - u32 timeout) -{ - dsaf_write_dev(rcb_common, RCB_CFG_OVERTIME_REG, timeout); + if (AE_IS_VER1(rcb_common->dsaf_dev->dsaf_ver)) + dsaf_write_dev(rcb_common, RCB_CFG_OVERTIME_REG, + timeout * HNS_RCB_CLK_FREQ_MHZ); + else + dsaf_write_dev(rcb_common, + RCB_PORT_CFG_OVERTIME_REG + port_idx * 4, + timeout); } static int hns_rcb_common_get_port_num(struct rcb_common_cb *rcb_common) @@ -361,10 +327,11 @@ int hns_rcb_common_init_hw(struct rcb_common_cb *rcb_common) for (i = 0; i < port_num; i++) { hns_rcb_set_port_desc_cnt(rcb_common, i, rcb_common->desc_num); - (void)hns_rcb_set_port_coalesced_frames( - rcb_common, i, rcb_common->coalesced_frames); + (void)hns_rcb_set_coalesced_frames( + rcb_common, i, HNS_RCB_DEF_COALESCED_FRAMES); + hns_rcb_set_port_timeout( + rcb_common, i, HNS_RCB_DEF_COALESCED_USECS); } - hns_rcb_set_timeout(rcb_common, rcb_common->timeout); dsaf_write_dev(rcb_common, RCB_COM_CFG_ENDIAN_REG, HNS_RCB_COMMON_ENDIAN); @@ -460,7 +427,8 @@ static void hns_rcb_ring_pair_get_cfg(struct ring_pair_cb *ring_pair_cb) hns_rcb_ring_get_cfg(&ring_pair_cb->q, TX_RING); } -static int hns_rcb_get_port(struct rcb_common_cb *rcb_common, int ring_idx) +static int hns_rcb_get_port_in_comm( + struct rcb_common_cb *rcb_common, int ring_idx) { int comm_index = rcb_common->comm_index; int port; @@ -470,7 +438,7 @@ static int hns_rcb_get_port(struct rcb_common_cb *rcb_common, int ring_idx) q_num = (int)rcb_common->max_q_per_vf * rcb_common->max_vfn; port = ring_idx / q_num; } else { - port = HNS_RCB_SERVICE_NW_ENGINE_NUM + comm_index - 1; + port = 0; /* config debug-ports port_id_in_comm to 0*/ } return port; @@ -518,7 +486,8 @@ void hns_rcb_get_cfg(struct rcb_common_cb *rcb_common) ring_pair_cb->index = i; ring_pair_cb->q.io_base = RCB_COMM_BASE_TO_RING_BASE(rcb_common->io_base, i); - ring_pair_cb->port_id_in_dsa = hns_rcb_get_port(rcb_common, i); + ring_pair_cb->port_id_in_comm = + hns_rcb_get_port_in_comm(rcb_common, i); ring_pair_cb->virq[HNS_RCB_IRQ_IDX_TX] = is_ver1 ? irq_of_parse_and_map(np, base_irq_idx + i * 2) : platform_get_irq(pdev, base_irq_idx + i * 3 + 1); @@ -534,82 +503,95 @@ void hns_rcb_get_cfg(struct rcb_common_cb *rcb_common) /** *hns_rcb_get_coalesced_frames - get rcb port coalesced frames *@rcb_common: rcb_common device - *@comm_index:port index - *return coalesced_frames + *@port_idx:port id in comm + * + *Returns: coalesced_frames */ -u32 hns_rcb_get_coalesced_frames(struct dsaf_device *dsaf_dev, int port) +u32 hns_rcb_get_coalesced_frames( + struct rcb_common_cb *rcb_common, u32 port_idx) { - int comm_index = hns_dsaf_get_comm_idx_by_port(port); - struct rcb_common_cb *rcb_comm = dsaf_dev->rcb_common[comm_index]; - - return hns_rcb_get_port_coalesced_frames(rcb_comm, port); + return dsaf_read_dev(rcb_common, RCB_CFG_PKTLINE_REG + port_idx * 4); } /** *hns_rcb_get_coalesce_usecs - get rcb port coalesced time_out *@rcb_common: rcb_common device - *@comm_index:port index - *return time_out + *@port_idx:port id in comm + * + *Returns: time_out */ -u32 hns_rcb_get_coalesce_usecs(struct dsaf_device *dsaf_dev, int comm_index) +u32 hns_rcb_get_coalesce_usecs( + struct rcb_common_cb *rcb_common, u32 port_idx) { - struct rcb_common_cb *rcb_comm = dsaf_dev->rcb_common[comm_index]; - - return rcb_comm->timeout; + if (AE_IS_VER1(rcb_common->dsaf_dev->dsaf_ver)) + return dsaf_read_dev(rcb_common, RCB_CFG_OVERTIME_REG) / + HNS_RCB_CLK_FREQ_MHZ; + else + return dsaf_read_dev(rcb_common, + RCB_PORT_CFG_OVERTIME_REG + port_idx * 4); } /** *hns_rcb_set_coalesce_usecs - set rcb port coalesced time_out *@rcb_common: rcb_common device - *@comm_index: comm :index - *@etx_usecs:tx time for coalesced time_out - *@rx_usecs:rx time for coalesced time_out + *@port_idx:port id in comm + *@timeout:tx/rx time for coalesced time_out + * + * Returns: + * Zero for success, or an error code in case of failure */ -void hns_rcb_set_coalesce_usecs(struct dsaf_device *dsaf_dev, - int port, u32 timeout) +int hns_rcb_set_coalesce_usecs( + struct rcb_common_cb *rcb_common, u32 port_idx, u32 timeout) { - int comm_index = hns_dsaf_get_comm_idx_by_port(port); - struct rcb_common_cb *rcb_comm = dsaf_dev->rcb_common[comm_index]; + u32 old_timeout = hns_rcb_get_coalesce_usecs(rcb_common, port_idx); - if (rcb_comm->timeout == timeout) - return; + if (timeout == old_timeout) + return 0; - if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) { - dev_err(dsaf_dev->dev, - "error: not support coalesce_usecs setting!\n"); - return; + if (AE_IS_VER1(rcb_common->dsaf_dev->dsaf_ver)) { + if (rcb_common->comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) { + dev_err(rcb_common->dsaf_dev->dev, + "error: not support coalesce_usecs setting!\n"); + return -EINVAL; + } } - rcb_comm->timeout = timeout; - hns_rcb_set_timeout(rcb_comm, rcb_comm->timeout); + if (timeout > HNS_RCB_MAX_COALESCED_USECS) { + dev_err(rcb_common->dsaf_dev->dev, + "error: not support coalesce %dus!\n", timeout); + return -EINVAL; + } + hns_rcb_set_port_timeout(rcb_common, port_idx, timeout); + return 0; } /** *hns_rcb_set_coalesced_frames - set rcb coalesced frames *@rcb_common: rcb_common device - *@tx_frames:tx BD num for coalesced frames - *@rx_frames:rx BD num for coalesced frames - *Return 0 on success, negative on failure + *@port_idx:port id in comm + *@coalesced_frames:tx/rx BD num for coalesced frames + * + * Returns: + * Zero for success, or an error code in case of failure */ -int hns_rcb_set_coalesced_frames(struct dsaf_device *dsaf_dev, - int port, u32 coalesced_frames) +int hns_rcb_set_coalesced_frames( + struct rcb_common_cb *rcb_common, u32 port_idx, u32 coalesced_frames) { - int comm_index = hns_dsaf_get_comm_idx_by_port(port); - struct rcb_common_cb *rcb_comm = dsaf_dev->rcb_common[comm_index]; - u32 coalesced_reg_val; - int ret; + u32 old_waterline = hns_rcb_get_coalesced_frames(rcb_common, port_idx); - coalesced_reg_val = hns_rcb_get_port_coalesced_frames(rcb_comm, port); - - if (coalesced_reg_val == coalesced_frames) + if (coalesced_frames == old_waterline) return 0; - if (coalesced_frames >= HNS_RCB_MIN_COALESCED_FRAMES) { - ret = hns_rcb_set_port_coalesced_frames(rcb_comm, port, - coalesced_frames); - return ret; - } else { + if (coalesced_frames >= rcb_common->desc_num || + coalesced_frames > HNS_RCB_MAX_COALESCED_FRAMES || + coalesced_frames < HNS_RCB_MIN_COALESCED_FRAMES) { + dev_err(rcb_common->dsaf_dev->dev, + "error: not support coalesce_frames setting!\n"); return -EINVAL; } + + dsaf_write_dev(rcb_common, RCB_CFG_PKTLINE_REG + port_idx * 4, + coalesced_frames); + return 0; } /** @@ -749,8 +731,6 @@ int hns_rcb_common_get_cfg(struct dsaf_device *dsaf_dev, rcb_common->dsaf_dev = dsaf_dev; rcb_common->desc_num = dsaf_dev->desc_num; - rcb_common->coalesced_frames = HNS_RCB_DEF_COALESCED_FRAMES; - rcb_common->timeout = HNS_RCB_MAX_TIME_OUT; hns_rcb_get_queue_mode(dsaf_mode, comm_index, &max_vfn, &max_q_per_vf); rcb_common->max_vfn = max_vfn; @@ -951,6 +931,10 @@ void hns_rcb_get_strings(int stringset, u8 *data, int index) void hns_rcb_get_common_regs(struct rcb_common_cb *rcb_com, void *data) { u32 *regs = data; + bool is_ver1 = AE_IS_VER1(rcb_com->dsaf_dev->dsaf_ver); + bool is_dbg = (rcb_com->comm_index != HNS_DSAF_COMM_SERVICE_NW_IDX); + u32 reg_tmp; + u32 reg_num_tmp; u32 i = 0; /*rcb common registers */ @@ -1004,12 +988,16 @@ void hns_rcb_get_common_regs(struct rcb_common_cb *rcb_com, void *data) = dsaf_read_dev(rcb_com, RCB_CFG_PKTLINE_REG + 4 * i); } - regs[70] = dsaf_read_dev(rcb_com, RCB_CFG_OVERTIME_REG); - regs[71] = dsaf_read_dev(rcb_com, RCB_CFG_PKTLINE_INT_NUM_REG); - regs[72] = dsaf_read_dev(rcb_com, RCB_CFG_OVERTIME_INT_NUM_REG); + reg_tmp = is_ver1 ? RCB_CFG_OVERTIME_REG : RCB_PORT_CFG_OVERTIME_REG; + reg_num_tmp = (is_ver1 || is_dbg) ? 1 : 6; + for (i = 0; i < reg_num_tmp; i++) + regs[70 + i] = dsaf_read_dev(rcb_com, reg_tmp); + + regs[76] = dsaf_read_dev(rcb_com, RCB_CFG_PKTLINE_INT_NUM_REG); + regs[77] = dsaf_read_dev(rcb_com, RCB_CFG_OVERTIME_INT_NUM_REG); /* mark end of rcb common regs */ - for (i = 73; i < 80; i++) + for (i = 78; i < 80; i++) regs[i] = 0xcccccccc; } diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h index 81fe9f849973..eb61014ad615 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h @@ -38,7 +38,9 @@ struct rcb_common_cb; #define HNS_RCB_MAX_COALESCED_FRAMES 1023 #define HNS_RCB_MIN_COALESCED_FRAMES 1 #define HNS_RCB_DEF_COALESCED_FRAMES 50 -#define HNS_RCB_MAX_TIME_OUT 0x500 +#define HNS_RCB_CLK_FREQ_MHZ 350 +#define HNS_RCB_MAX_COALESCED_USECS 0x3ff +#define HNS_RCB_DEF_COALESCED_USECS 3 #define HNS_RCB_COMMON_ENDIAN 1 @@ -82,7 +84,7 @@ struct ring_pair_cb { int virq[HNS_RCB_IRQ_NUM_PER_QUEUE]; - u8 port_id_in_dsa; + u8 port_id_in_comm; u8 used_by_vf; struct hns_ring_hw_stats hw_stats; @@ -97,8 +99,6 @@ struct rcb_common_cb { u8 comm_index; u32 ring_num; - u32 coalesced_frames; /* frames threshold of rx interrupt */ - u32 timeout; /* time threshold of rx interrupt */ u32 desc_num; /* desc num per queue*/ struct ring_pair_cb ring_pair_cb[0]; @@ -125,13 +125,14 @@ void hns_rcbv2_int_clr_hw(struct hnae_queue *q, u32 flag); void hns_rcb_init_hw(struct ring_pair_cb *ring); void hns_rcb_reset_ring_hw(struct hnae_queue *q); void hns_rcb_wait_fbd_clean(struct hnae_queue **qs, int q_num, u32 flag); - -u32 hns_rcb_get_coalesced_frames(struct dsaf_device *dsaf_dev, int comm_index); -u32 hns_rcb_get_coalesce_usecs(struct dsaf_device *dsaf_dev, int comm_index); -void hns_rcb_set_coalesce_usecs(struct dsaf_device *dsaf_dev, - int comm_index, u32 timeout); -int hns_rcb_set_coalesced_frames(struct dsaf_device *dsaf_dev, - int comm_index, u32 coalesce_frames); +u32 hns_rcb_get_coalesced_frames( + struct rcb_common_cb *rcb_common, u32 port_idx); +u32 hns_rcb_get_coalesce_usecs( + struct rcb_common_cb *rcb_common, u32 port_idx); +int hns_rcb_set_coalesce_usecs( + struct rcb_common_cb *rcb_common, u32 port_idx, u32 timeout); +int hns_rcb_set_coalesced_frames( + struct rcb_common_cb *rcb_common, u32 port_idx, u32 coalesced_frames); void hns_rcb_update_stats(struct hnae_queue *queue); void hns_rcb_get_stats(struct hnae_queue *queue, u64 *data); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h index e2206f938a9c..7d7204f45e78 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h @@ -406,6 +406,7 @@ #define RCB_CFG_OVERTIME_REG 0x9300 #define RCB_CFG_PKTLINE_INT_NUM_REG 0x9304 #define RCB_CFG_OVERTIME_INT_NUM_REG 0x9308 +#define RCB_PORT_CFG_OVERTIME_REG 0x9430 #define RCB_RING_RX_RING_BASEADDR_L_REG 0x00000 #define RCB_RING_RX_RING_BASEADDR_H_REG 0x00004 -- cgit From 9832ce4c0bb90e4dcedf4280947341b1eb6728e6 Mon Sep 17 00:00:00 2001 From: Lisheng Date: Mon, 28 Mar 2016 18:40:57 +0800 Subject: net: hns: set-coalesce-usecs returns errno by dsaf.ko It may fail to set coalesce usecs to HW, and Ethtool needs to know if it is successful to cfg the parameter or not. So it needs return the errno by dsaf.ko. Signed-off-by: Lisheng Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hnae.h | 2 +- drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c | 6 +++--- drivers/net/ethernet/hisilicon/hns/hns_ethtool.c | 6 ++++-- 3 files changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h index 37d0cce392be..e8d36aaea223 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.h +++ b/drivers/net/ethernet/hisilicon/hns/hnae.h @@ -469,7 +469,7 @@ struct hnae_ae_ops { u32 *tx_usecs, u32 *rx_usecs); void (*get_rx_max_coalesced_frames)(struct hnae_handle *handle, u32 *tx_frames, u32 *rx_frames); - void (*set_coalesce_usecs)(struct hnae_handle *handle, u32 timeout); + int (*set_coalesce_usecs)(struct hnae_handle *handle, u32 timeout); int (*set_coalesce_frames)(struct hnae_handle *handle, u32 coalesce_frames); void (*set_promisc_mode)(struct hnae_handle *handle, u32 en); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c index 1dd1d6974d47..a1cb461ac45f 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c @@ -469,13 +469,13 @@ static void hns_ae_get_rx_max_coalesced_frames(struct hnae_handle *handle, ring_pair->port_id_in_comm); } -static void hns_ae_set_coalesce_usecs(struct hnae_handle *handle, - u32 timeout) +static int hns_ae_set_coalesce_usecs(struct hnae_handle *handle, + u32 timeout) { struct ring_pair_cb *ring_pair = container_of(handle->qs[0], struct ring_pair_cb, q); - (void)hns_rcb_set_coalesce_usecs( + return hns_rcb_set_coalesce_usecs( ring_pair->rcb_common, ring_pair->port_id_in_comm, timeout); } diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c index 0e7da3f0a564..3d746c887873 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c @@ -794,8 +794,10 @@ static int hns_set_coalesce(struct net_device *net_dev, (!ops->set_coalesce_frames)) return -ESRCH; - ops->set_coalesce_usecs(priv->ae_handle, - ec->rx_coalesce_usecs); + ret = ops->set_coalesce_usecs(priv->ae_handle, + ec->rx_coalesce_usecs); + if (ret) + return ret; ret = ops->set_coalesce_frames( priv->ae_handle, -- cgit From 0e3e7999703e7df93a9deee8ba89b604c5fd662d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 28 Mar 2016 13:47:42 +0100 Subject: net: macb: Only call GPIO functions if there is a valid GPIO GPIOlib will print warning messages if we call GPIO functions without a valid GPIO. Change the code to avoid doing so. Signed-off-by: Charles Keepax Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 6c3dc27cb100..48a7d7dee846 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -2996,9 +2996,10 @@ static int macb_probe(struct platform_device *pdev) phy_node = of_get_next_available_child(np, NULL); if (phy_node) { int gpio = of_get_named_gpio(phy_node, "reset-gpios", 0); - if (gpio_is_valid(gpio)) + if (gpio_is_valid(gpio)) { bp->reset_gpio = gpio_to_desc(gpio); - gpiod_direction_output(bp->reset_gpio, 1); + gpiod_direction_output(bp->reset_gpio, 1); + } } of_node_put(phy_node); @@ -3068,7 +3069,8 @@ static int macb_remove(struct platform_device *pdev) mdiobus_free(bp->mii_bus); /* Shutdown the PHY if there is a GPIO reset */ - gpiod_set_value(bp->reset_gpio, 0); + if (bp->reset_gpio) + gpiod_set_value(bp->reset_gpio, 0); unregister_netdev(dev); clk_disable_unprepare(bp->tx_clk); -- cgit From e1a575ada8d2a3c3f107fdd12ac9215f983a7c80 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Mon, 28 Mar 2016 16:39:14 +0900 Subject: drm/radeon: Don't move pinned BOs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The purpose of pinning is to prevent a buffer from moving. Reviewed-by: Christian König Signed-off-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_object.c | 4 ++++ drivers/gpu/drm/radeon/radeon_ttm.c | 6 ++++++ 2 files changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index dd46c38676db..2d901bf28a94 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -799,6 +799,10 @@ int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo) if ((offset + size) <= rdev->mc.visible_vram_size) return 0; + /* Can't move a pinned BO to visible VRAM */ + if (rbo->pin_count > 0) + return -EINVAL; + /* hurrah the memory is not visible ! */ radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM); lpfn = rdev->mc.visible_vram_size >> PAGE_SHIFT; diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index e06ac546a90f..636c1cf7d106 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -397,9 +397,15 @@ static int radeon_bo_move(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) { struct radeon_device *rdev; + struct radeon_bo *rbo; struct ttm_mem_reg *old_mem = &bo->mem; int r; + /* Can't move a pinned BO */ + rbo = container_of(bo, struct radeon_bo, tbo); + if (WARN_ON_ONCE(rbo->pin_count > 0)) + return -EINVAL; + rdev = radeon_get_rdev(bo->bdev); if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { radeon_move_null(bo, new_mem); -- cgit From 104ece975746d94b8276cd7f38d6b5c056d700b5 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Mon, 28 Mar 2016 12:53:02 +0900 Subject: drm/amdgpu: Don't move pinned BOs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The purpose of pinning is to prevent a buffer from moving. Reviewed-by: Christian König Tested-by: Rex Zhu Signed-off-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 4 ++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 6 ++++++ 2 files changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 151a2d42c639..56d1458393cc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -608,6 +608,10 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) if ((offset + size) <= adev->mc.visible_vram_size) return 0; + /* Can't move a pinned BO to visible VRAM */ + if (abo->pin_count > 0) + return -EINVAL; + /* hurrah the memory is not visible ! */ amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_VRAM); lpfn = adev->mc.visible_vram_size >> PAGE_SHIFT; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 0f42b1a24446..9d3341dbeb04 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -384,9 +384,15 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) { struct amdgpu_device *adev; + struct amdgpu_bo *abo; struct ttm_mem_reg *old_mem = &bo->mem; int r; + /* Can't move a pinned BO */ + abo = container_of(bo, struct amdgpu_bo, tbo); + if (WARN_ON_ONCE(abo->pin_count > 0)) + return -EINVAL; + adev = amdgpu_get_adev(bo->bdev); if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { amdgpu_move_null(bo, new_mem); -- cgit From 4b28038fd60d346337dcaca80c255db2724adf76 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Sat, 19 Mar 2016 15:31:10 +0200 Subject: remoteproc: st: fix check of syscon_regmap_lookup_by_phandle() return value syscon_regmap_lookup_by_phandle() returns either a valid pointer to struct regmap or ERR_PTR() error value, check for NULL is invalid and on error path may lead to oops, the change corrects the check. Signed-off-by: Vladimir Zapolskiy Acked-by: Lee Jones Signed-off-by: Bjorn Andersson --- drivers/remoteproc/st_remoteproc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/remoteproc/st_remoteproc.c b/drivers/remoteproc/st_remoteproc.c index 6bb04d453247..6f056caa8a56 100644 --- a/drivers/remoteproc/st_remoteproc.c +++ b/drivers/remoteproc/st_remoteproc.c @@ -189,9 +189,9 @@ static int st_rproc_parse_dt(struct platform_device *pdev) } ddata->boot_base = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); - if (!ddata->boot_base) { + if (IS_ERR(ddata->boot_base)) { dev_err(dev, "Boot base not found\n"); - return -EINVAL; + return PTR_ERR(ddata->boot_base); } err = of_property_read_u32_index(np, "st,syscfg", 1, -- cgit From e84810c7b85a2d7897797b3ad3e879168a8e032a Mon Sep 17 00:00:00 2001 From: Bjørn Mork Date: Mon, 28 Mar 2016 22:38:16 +0200 Subject: qmi_wwan: add "D-Link DWM-221 B1" device id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thomas reports: "Windows: 00 diagnostics 01 modem 02 at-port 03 nmea 04 nic Linux: T: Bus=02 Lev=01 Prnt=01 Port=03 Cnt=01 Dev#= 4 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=2001 ProdID=7e19 Rev=02.32 S: Manufacturer=Mobile Connect S: Product=Mobile Connect S: SerialNumber=0123456789ABCDEF C: #Ifs= 6 Cfg#= 1 Atr=a0 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option I: If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option I: If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option I: If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option I: If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan I: If#= 5 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage" Reported-by: Thomas Schäfer Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 7d717c66bcb0..9d1fce8a6e84 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -844,6 +844,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x19d2, 0x1426, 2)}, /* ZTE MF91 */ {QMI_FIXED_INTF(0x19d2, 0x1428, 2)}, /* Telewell TW-LTE 4G v2 */ {QMI_FIXED_INTF(0x19d2, 0x2002, 4)}, /* ZTE (Vodafone) K3765-Z */ + {QMI_FIXED_INTF(0x2001, 0x7e19, 4)}, /* D-Link DWM-221 B1 */ {QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)}, /* Sierra Wireless MC7700 */ {QMI_FIXED_INTF(0x114f, 0x68a2, 8)}, /* Sierra Wireless MC7750 */ {QMI_FIXED_INTF(0x1199, 0x68a2, 8)}, /* Sierra Wireless MC7710 in QMI mode */ -- cgit From fc0c2028135c7f75fce36b90e44efb8003a9173b Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 8 Mar 2016 10:30:19 -0800 Subject: x86, pmem: use memcpy_mcsafe() for memcpy_from_pmem() Update the definition of memcpy_from_pmem() to return 0 or a negative error code. Implement x86/arch_memcpy_from_pmem() with memcpy_mcsafe(). Cc: Borislav Petkov Cc: Tony Luck Cc: Thomas Gleixner Cc: Andy Lutomirski Cc: Peter Zijlstra Cc: Andrew Morton Cc: Linus Torvalds Acked-by: Ingo Molnar Reviewed-by: Ross Zwisler Signed-off-by: Dan Williams --- drivers/nvdimm/pmem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index ca5721c306bb..cc31c6f1f88e 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -99,7 +99,7 @@ static int pmem_do_bvec(struct pmem_device *pmem, struct page *page, if (unlikely(bad_pmem)) rc = -EIO; else { - memcpy_from_pmem(mem + off, pmem_addr, len); + rc = memcpy_from_pmem(mem + off, pmem_addr, len); flush_dcache_page(page); } } else { @@ -295,7 +295,7 @@ static int pmem_rw_bytes(struct nd_namespace_common *ndns, if (unlikely(is_bad_pmem(&pmem->bb, offset / 512, sz_align))) return -EIO; - memcpy_from_pmem(buf, pmem->virt_addr + offset, size); + return memcpy_from_pmem(buf, pmem->virt_addr + offset, size); } else { memcpy_to_pmem(pmem->virt_addr + offset, buf, size); wmb_pmem(); -- cgit From f39bb4579cbf3ff174d936d37aa3669eb98370c6 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 25 Feb 2016 10:45:06 +0100 Subject: clk: mediatek: Make reset_control_ops const The mtk_reset_ops structure is never modified. Make it const. Signed-off-by: Philipp Zabel Reviewed-by: Matthias Brugger Signed-off-by: Stephen Boyd --- drivers/clk/mediatek/reset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/mediatek/reset.c b/drivers/clk/mediatek/reset.c index 9e9fe4b19ac4..309049d41f1b 100644 --- a/drivers/clk/mediatek/reset.c +++ b/drivers/clk/mediatek/reset.c @@ -57,7 +57,7 @@ static int mtk_reset(struct reset_controller_dev *rcdev, return mtk_reset_deassert(rcdev, id); } -static struct reset_control_ops mtk_reset_ops = { +static const struct reset_control_ops mtk_reset_ops = { .assert = mtk_reset_assert, .deassert = mtk_reset_deassert, .reset = mtk_reset, -- cgit From fd92f41dc2527722e5fd63f859ff811482f0ce1a Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 25 Feb 2016 10:45:07 +0100 Subject: clk: mmp: Make reset_control_ops const The mmp_clk_reset_ops structure is never modified. Make it const. Signed-off-by: Philipp Zabel Signed-off-by: Stephen Boyd --- drivers/clk/mmp/reset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/mmp/reset.c b/drivers/clk/mmp/reset.c index b54da1fe73f0..b4e4d6aa2631 100644 --- a/drivers/clk/mmp/reset.c +++ b/drivers/clk/mmp/reset.c @@ -74,7 +74,7 @@ static int mmp_clk_reset_deassert(struct reset_controller_dev *rcdev, return 0; } -static struct reset_control_ops mmp_clk_reset_ops = { +static const struct reset_control_ops mmp_clk_reset_ops = { .assert = mmp_clk_reset_assert, .deassert = mmp_clk_reset_deassert, }; -- cgit From 3fb950fea6e14b159899b713ede0b7506ca03649 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 25 Feb 2016 10:45:08 +0100 Subject: clk: rockchip: Make reset_control_ops const The rockchip_softrst_ops structure is never modified. Make it const. Signed-off-by: Philipp Zabel Reviewed-by: Heiko Stuebner Signed-off-by: Stephen Boyd --- drivers/clk/rockchip/softrst.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/rockchip/softrst.c b/drivers/clk/rockchip/softrst.c index 552f7bb15bc5..21218987bbc3 100644 --- a/drivers/clk/rockchip/softrst.c +++ b/drivers/clk/rockchip/softrst.c @@ -81,7 +81,7 @@ static int rockchip_softrst_deassert(struct reset_controller_dev *rcdev, return 0; } -static struct reset_control_ops rockchip_softrst_ops = { +static const struct reset_control_ops rockchip_softrst_ops = { .assert = rockchip_softrst_assert, .deassert = rockchip_softrst_deassert, }; -- cgit From b1b69c5dd5ada9be222721dd297c329dafb65d06 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 25 Feb 2016 10:45:09 +0100 Subject: clk: atlas7: Make reset_control_ops const The atlas7_rst_ops structure is never modified. Make it const. Signed-off-by: Philipp Zabel Signed-off-by: Stephen Boyd --- drivers/clk/sirf/clk-atlas7.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/sirf/clk-atlas7.c b/drivers/clk/sirf/clk-atlas7.c index 957aae63e7cc..d0c6c9a2d06a 100644 --- a/drivers/clk/sirf/clk-atlas7.c +++ b/drivers/clk/sirf/clk-atlas7.c @@ -1423,7 +1423,7 @@ static int atlas7_reset_module(struct reset_controller_dev *rcdev, return 0; } -static struct reset_control_ops atlas7_rst_ops = { +static const struct reset_control_ops atlas7_rst_ops = { .reset = atlas7_reset_module, }; -- cgit From 5e7bc9c6cee68fdd3583eb689583214a3d56341e Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 25 Feb 2016 10:45:10 +0100 Subject: clk: sunxi: Make reset_control_ops const The sunxi_ve_reset_ops, sun9i_mmc_reset_ops, and sunxi_usb_reset_ops structures are never modified. Make them const. Signed-off-by: Philipp Zabel Signed-off-by: Stephen Boyd --- drivers/clk/sunxi/clk-a10-ve.c | 2 +- drivers/clk/sunxi/clk-sun9i-mmc.c | 2 +- drivers/clk/sunxi/clk-usb.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk-a10-ve.c b/drivers/clk/sunxi/clk-a10-ve.c index 044c1717b762..d9ea22ec4e25 100644 --- a/drivers/clk/sunxi/clk-a10-ve.c +++ b/drivers/clk/sunxi/clk-a10-ve.c @@ -85,7 +85,7 @@ static int sunxi_ve_of_xlate(struct reset_controller_dev *rcdev, return 0; } -static struct reset_control_ops sunxi_ve_reset_ops = { +static const struct reset_control_ops sunxi_ve_reset_ops = { .assert = sunxi_ve_reset_assert, .deassert = sunxi_ve_reset_deassert, }; diff --git a/drivers/clk/sunxi/clk-sun9i-mmc.c b/drivers/clk/sunxi/clk-sun9i-mmc.c index a9b176139aca..028dd832a39f 100644 --- a/drivers/clk/sunxi/clk-sun9i-mmc.c +++ b/drivers/clk/sunxi/clk-sun9i-mmc.c @@ -83,7 +83,7 @@ static int sun9i_mmc_reset_deassert(struct reset_controller_dev *rcdev, return 0; } -static struct reset_control_ops sun9i_mmc_reset_ops = { +static const struct reset_control_ops sun9i_mmc_reset_ops = { .assert = sun9i_mmc_reset_assert, .deassert = sun9i_mmc_reset_deassert, }; diff --git a/drivers/clk/sunxi/clk-usb.c b/drivers/clk/sunxi/clk-usb.c index 5432b1c198a4..fe0c3d169377 100644 --- a/drivers/clk/sunxi/clk-usb.c +++ b/drivers/clk/sunxi/clk-usb.c @@ -76,7 +76,7 @@ static int sunxi_usb_reset_deassert(struct reset_controller_dev *rcdev, return 0; } -static struct reset_control_ops sunxi_usb_reset_ops = { +static const struct reset_control_ops sunxi_usb_reset_ops = { .assert = sunxi_usb_reset_assert, .deassert = sunxi_usb_reset_deassert, }; -- cgit From 7ba256d2aa2a18e24b7c9ec4e03cd22b0149c51c Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 25 Feb 2016 10:45:11 +0100 Subject: clk: tegra: Make reset_control_ops const The rst_ops structure is never modified. Make it const. Signed-off-by: Philipp Zabel Signed-off-by: Stephen Boyd --- drivers/clk/tegra/clk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c index 2a3a4fe803d6..f60fe2e344ca 100644 --- a/drivers/clk/tegra/clk.c +++ b/drivers/clk/tegra/clk.c @@ -271,7 +271,7 @@ void __init tegra_init_from_table(struct tegra_clk_init_table *tbl, } } -static struct reset_control_ops rst_ops = { +static const struct reset_control_ops rst_ops = { .assert = tegra_clk_rst_assert, .deassert = tegra_clk_rst_deassert, }; -- cgit From add479eeb1a208a31ab913ae7c97506a81383079 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 25 Feb 2016 10:45:12 +0100 Subject: clk: qcom: Make reset_control_ops const The qcom_reset_ops structure is never modified. Make it const. Signed-off-by: Philipp Zabel Signed-off-by: Stephen Boyd --- drivers/clk/qcom/reset.c | 2 +- drivers/clk/qcom/reset.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/qcom/reset.c b/drivers/clk/qcom/reset.c index 6c977d3a8590..0324d8daab9b 100644 --- a/drivers/clk/qcom/reset.c +++ b/drivers/clk/qcom/reset.c @@ -55,7 +55,7 @@ qcom_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id) return regmap_update_bits(rst->regmap, map->reg, mask, 0); } -struct reset_control_ops qcom_reset_ops = { +const struct reset_control_ops qcom_reset_ops = { .reset = qcom_reset, .assert = qcom_reset_assert, .deassert = qcom_reset_deassert, diff --git a/drivers/clk/qcom/reset.h b/drivers/clk/qcom/reset.h index 0e11e2130f97..cda877927d43 100644 --- a/drivers/clk/qcom/reset.h +++ b/drivers/clk/qcom/reset.h @@ -32,6 +32,6 @@ struct qcom_reset_controller { #define to_qcom_reset_controller(r) \ container_of(r, struct qcom_reset_controller, rcdev); -extern struct reset_control_ops qcom_reset_ops; +extern const struct reset_control_ops qcom_reset_ops; #endif -- cgit From bc95d4f0a920150e77083c2946fe7b7d2f6e217c Mon Sep 17 00:00:00 2001 From: Matthew McClintock Date: Wed, 23 Mar 2016 17:04:59 -0500 Subject: clk: qcom: ipq4019: switch remaining defines to enums When this was added not all the remaining defines were switched over to use enums, so let's complete that process here Reported-by: Stephen Boyd Signed-off-by: Matthew McClintock Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-ipq4019.c | 60 ++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/qcom/gcc-ipq4019.c b/drivers/clk/qcom/gcc-ipq4019.c index 5428efb9fbf5..3599ade11b0c 100644 --- a/drivers/clk/qcom/gcc-ipq4019.c +++ b/drivers/clk/qcom/gcc-ipq4019.c @@ -129,20 +129,10 @@ static const char * const gcc_xo_ddr_500_200[] = { }; #define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } -#define P_XO 0 -#define FE_PLL_200 1 -#define FE_PLL_500 2 -#define DDRC_PLL_666 3 - -#define DDRC_PLL_666_SDCC 1 -#define FE_PLL_125_DLY 1 - -#define FE_PLL_WCSS2G 1 -#define FE_PLL_WCSS5G 1 static const struct freq_tbl ftbl_gcc_audio_pwm_clk[] = { F(48000000, P_XO, 1, 0, 0), - F(200000000, FE_PLL_200, 1, 0, 0), + F(200000000, P_FEPLL200, 1, 0, 0), { } }; @@ -334,15 +324,15 @@ static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = { }; static const struct freq_tbl ftbl_gcc_blsp1_uart1_2_apps_clk[] = { - F(1843200, FE_PLL_200, 1, 144, 15625), - F(3686400, FE_PLL_200, 1, 288, 15625), - F(7372800, FE_PLL_200, 1, 576, 15625), - F(14745600, FE_PLL_200, 1, 1152, 15625), - F(16000000, FE_PLL_200, 1, 2, 25), + F(1843200, P_FEPLL200, 1, 144, 15625), + F(3686400, P_FEPLL200, 1, 288, 15625), + F(7372800, P_FEPLL200, 1, 576, 15625), + F(14745600, P_FEPLL200, 1, 1152, 15625), + F(16000000, P_FEPLL200, 1, 2, 25), F(24000000, P_XO, 1, 1, 2), - F(32000000, FE_PLL_200, 1, 4, 25), - F(40000000, FE_PLL_200, 1, 1, 5), - F(46400000, FE_PLL_200, 1, 29, 125), + F(32000000, P_FEPLL200, 1, 4, 25), + F(40000000, P_FEPLL200, 1, 1, 5), + F(46400000, P_FEPLL200, 1, 29, 125), F(48000000, P_XO, 1, 0, 0), { } }; @@ -410,9 +400,9 @@ static struct clk_branch gcc_blsp1_uart2_apps_clk = { }; static const struct freq_tbl ftbl_gcc_gp_clk[] = { - F(1250000, FE_PLL_200, 1, 16, 0), - F(2500000, FE_PLL_200, 1, 8, 0), - F(5000000, FE_PLL_200, 1, 4, 0), + F(1250000, P_FEPLL200, 1, 16, 0), + F(2500000, P_FEPLL200, 1, 8, 0), + F(5000000, P_FEPLL200, 1, 4, 0), { } }; @@ -512,11 +502,11 @@ static struct clk_branch gcc_gp3_clk = { static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk[] = { F(144000, P_XO, 1, 3, 240), F(400000, P_XO, 1, 1, 0), - F(20000000, FE_PLL_500, 1, 1, 25), - F(25000000, FE_PLL_500, 1, 1, 20), - F(50000000, FE_PLL_500, 1, 1, 10), - F(100000000, FE_PLL_500, 1, 1, 5), - F(193000000, DDRC_PLL_666_SDCC, 1, 0, 0), + F(20000000, P_FEPLL500, 1, 1, 25), + F(25000000, P_FEPLL500, 1, 1, 20), + F(50000000, P_FEPLL500, 1, 1, 10), + F(100000000, P_FEPLL500, 1, 1, 5), + F(193000000, P_DDRPLL, 1, 0, 0), { } }; @@ -536,9 +526,9 @@ static struct clk_rcg2 sdcc1_apps_clk_src = { static const struct freq_tbl ftbl_gcc_apps_clk[] = { F(48000000, P_XO, 1, 0, 0), - F(200000000, FE_PLL_200, 1, 0, 0), - F(500000000, FE_PLL_500, 1, 0, 0), - F(626000000, DDRC_PLL_666, 1, 0, 0), + F(200000000, P_FEPLL200, 1, 0, 0), + F(500000000, P_FEPLL500, 1, 0, 0), + F(626000000, P_DDRPLLAPSS, 1, 0, 0), { } }; @@ -557,7 +547,7 @@ static struct clk_rcg2 apps_clk_src = { static const struct freq_tbl ftbl_gcc_apps_ahb_clk[] = { F(48000000, P_XO, 1, 0, 0), - F(100000000, FE_PLL_200, 2, 0, 0), + F(100000000, P_FEPLL200, 2, 0, 0), { } }; @@ -940,7 +930,7 @@ static struct clk_branch gcc_usb2_mock_utmi_clk = { }; static const struct freq_tbl ftbl_gcc_usb30_mock_utmi_clk[] = { - F(2000000, FE_PLL_200, 10, 0, 0), + F(2000000, P_FEPLL200, 10, 0, 0), { } }; @@ -1007,7 +997,7 @@ static struct clk_branch gcc_usb3_mock_utmi_clk = { }; static const struct freq_tbl ftbl_gcc_fephy_dly_clk[] = { - F(125000000, FE_PLL_125_DLY, 1, 0, 0), + F(125000000, P_FEPLL125DLY, 1, 0, 0), { } }; @@ -1027,7 +1017,7 @@ static struct clk_rcg2 fephy_125m_dly_clk_src = { static const struct freq_tbl ftbl_gcc_wcss2g_clk[] = { F(48000000, P_XO, 1, 0, 0), - F(250000000, FE_PLL_WCSS2G, 1, 0, 0), + F(250000000, P_FEPLLWCSS2G, 1, 0, 0), { } }; @@ -1097,7 +1087,7 @@ static struct clk_branch gcc_wcss2g_rtc_clk = { static const struct freq_tbl ftbl_gcc_wcss5g_clk[] = { F(48000000, P_XO, 1, 0, 0), - F(250000000, FE_PLL_WCSS5G, 1, 0, 0), + F(250000000, P_FEPLLWCSS5G, 1, 0, 0), { } }; -- cgit From 2aac7ddf9a410e3418c9cc69618f304550466793 Mon Sep 17 00:00:00 2001 From: Matthew McClintock Date: Wed, 23 Mar 2016 17:05:00 -0500 Subject: clk: qcom: ipq4019: add some fixed clocks for ddrppl and fepll Drivers for these don't exist yet so we will add them as fixed clocks so we don't BUG() if we change clocks that reference these clocks. Signed-off-by: Matthew McClintock Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-ipq4019.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/qcom/gcc-ipq4019.c b/drivers/clk/qcom/gcc-ipq4019.c index 3599ade11b0c..3cd1af0af0d9 100644 --- a/drivers/clk/qcom/gcc-ipq4019.c +++ b/drivers/clk/qcom/gcc-ipq4019.c @@ -1315,6 +1315,16 @@ MODULE_DEVICE_TABLE(of, gcc_ipq4019_match_table); static int gcc_ipq4019_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; + + clk_register_fixed_rate(dev, "fepll125", "xo", 0, 200000000); + clk_register_fixed_rate(dev, "fepll125dly", "xo", 0, 200000000); + clk_register_fixed_rate(dev, "fepllwcss2g", "xo", 0, 200000000); + clk_register_fixed_rate(dev, "fepllwcss5g", "xo", 0, 200000000); + clk_register_fixed_rate(dev, "fepll200", "xo", 0, 200000000); + clk_register_fixed_rate(dev, "fepll500", "xo", 0, 200000000); + clk_register_fixed_rate(dev, "ddrpllapss", "xo", 0, 666000000); + return qcom_cc_probe(pdev, &gcc_ipq4019_desc); } -- cgit From 56768045186c183f1d6e5cd916dd07751a777a8d Mon Sep 17 00:00:00 2001 From: Tushar Dave Date: Thu, 7 Jan 2016 14:17:03 -0800 Subject: ixgbe: Fix for RAR0 not being set to default MAC addr commit c9f53e63c208 ("ixgbe: Refactor MAC address configuration code") introduced code that doesn't set HW register RAR0 to default mac address but FF:FF:FF:FF:FF:FF. Due to this, ixgbe HW discards all incoming packets that doesn't have destination mac address equals to FF:FF:FF:FF:FF:FF. This commit sets RAR0 correctly to default HW mac address. Signed-off-by: Tushar Dave Tested-by: Sowmini Varadhan Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 569cb0757c93..f19327325675 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -9329,6 +9329,8 @@ skip_sriov: goto err_sw_init; } + /* Set hw->mac.addr to permanent MAC address */ + ether_addr_copy(hw->mac.addr, hw->mac.perm_addr); ixgbe_mac_set_default_filter(adapter); setup_timer(&adapter->service_timer, &ixgbe_service_timer, -- cgit From 9f12df906cd807a05d71aa53a951532d1dd3b888 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Mon, 25 Jan 2016 19:36:29 -0800 Subject: ixgbe: Store VXLAN port number in network order The VXLAN port number should be stored in network order instead of in host order as it is accessed from the hot-path in ATR. This way we can avoid having to do any byte swaps in order to validate the port number. I moved the vxlan_port value into a hole in the read-mostly region of the adapter struct. This way it should be in a warm cache-line instead of in some isolated region in memory when it needs to be accessed. In addition I went through and stripped a bunch of unneeded ifdef flags since having an extra variable present doesn't really hurt anything and makes the code easier to read. I also went through and dropped the NETIF_F_RXCSUM flag which was being set in hw_encap_features but provides no value as the flag is not evaluated in the Rx path. Signed-off-by: Alexander Duyck Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 8 ++-- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 61 ++++++++------------------- 2 files changed, 20 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 84fa28ceb200..458549c06a4f 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -661,9 +661,7 @@ struct ixgbe_adapter { #define IXGBE_FLAG2_RSS_FIELD_IPV6_UDP (u32)(1 << 9) #define IXGBE_FLAG2_PTP_PPS_ENABLED (u32)(1 << 10) #define IXGBE_FLAG2_PHY_INTERRUPT (u32)(1 << 11) -#ifdef CONFIG_IXGBE_VXLAN #define IXGBE_FLAG2_VXLAN_REREG_NEEDED BIT(12) -#endif #define IXGBE_FLAG2_VLAN_PROMISC BIT(13) /* Tx fast path data */ @@ -675,6 +673,9 @@ struct ixgbe_adapter { int num_rx_queues; u16 rx_itr_setting; + /* Port number used to identify VXLAN traffic */ + __be16 vxlan_port; + /* TX */ struct ixgbe_ring *tx_ring[MAX_TX_QUEUES] ____cacheline_aligned_in_smp; @@ -782,9 +783,6 @@ struct ixgbe_adapter { u32 timer_event_accumulator; u32 vferr_refcount; struct ixgbe_mac_addr *mac_table; -#ifdef CONFIG_IXGBE_VXLAN - u16 vxlan_port; -#endif struct kobject *info_kobj; #ifdef CONFIG_IXGBE_HWMON struct hwmon_buff *ixgbe_hwmon_buff; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index f19327325675..f67c9a6429ac 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -4531,9 +4531,7 @@ static void ixgbe_clear_vxlan_port(struct ixgbe_adapter *adapter) case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: IXGBE_WRITE_REG(&adapter->hw, IXGBE_VXLANCTRL, 0); -#ifdef CONFIG_IXGBE_VXLAN adapter->vxlan_port = 0; -#endif break; default: break; @@ -7561,9 +7559,6 @@ static void ixgbe_atr(struct ixgbe_ring *ring, } hdr; struct tcphdr *th; struct sk_buff *skb; -#ifdef CONFIG_IXGBE_VXLAN - u8 encap = false; -#endif /* CONFIG_IXGBE_VXLAN */ __be16 vlan_id; /* if ring doesn't have a interrupt vector, cannot perform ATR */ @@ -7579,28 +7574,21 @@ static void ixgbe_atr(struct ixgbe_ring *ring, /* snag network header to get L4 type and address */ skb = first->skb; hdr.network = skb_network_header(skb); - if (!skb->encapsulation) { - th = tcp_hdr(skb); - } else { + th = tcp_hdr(skb); #ifdef CONFIG_IXGBE_VXLAN + if (skb->encapsulation && + first->protocol == htons(ETH_P_IP) && + hdr.ipv4->protocol != IPPROTO_UDP) { struct ixgbe_adapter *adapter = q_vector->adapter; - if (!adapter->vxlan_port) - return; - if (first->protocol != htons(ETH_P_IP) || - hdr.ipv4->version != IPVERSION || - hdr.ipv4->protocol != IPPROTO_UDP) { - return; + /* verify the port is recognized as VXLAN */ + if (adapter->vxlan_port && + udp_hdr(skb)->dest == adapter->vxlan_port) { + hdr.network = skb_inner_network_header(skb); + th = inner_tcp_hdr(skb); } - if (ntohs(udp_hdr(skb)->dest) != adapter->vxlan_port) - return; - encap = true; - hdr.network = skb_inner_network_header(skb); - th = inner_tcp_hdr(skb); -#else - return; -#endif /* CONFIG_IXGBE_VXLAN */ } +#endif /* CONFIG_IXGBE_VXLAN */ /* Currently only IPv4/IPv6 with TCP is supported */ switch (hdr.ipv4->version) { @@ -7682,10 +7670,8 @@ static void ixgbe_atr(struct ixgbe_ring *ring, break; } -#ifdef CONFIG_IXGBE_VXLAN - if (encap) + if (hdr.network != skb_network_header(skb)) input.formatted.flow_type |= IXGBE_ATR_L4TYPE_TUNNEL_MASK; -#endif /* CONFIG_IXGBE_VXLAN */ /* This assumes the Rx queue and Tx queue are bound to the same CPU */ ixgbe_fdir_add_signature_filter_82599(&q_vector->adapter->hw, @@ -8554,7 +8540,6 @@ static void ixgbe_add_vxlan_port(struct net_device *dev, sa_family_t sa_family, { struct ixgbe_adapter *adapter = netdev_priv(dev); struct ixgbe_hw *hw = &adapter->hw; - u16 new_port = ntohs(port); if (!(adapter->flags & IXGBE_FLAG_VXLAN_OFFLOAD_CAPABLE)) return; @@ -8562,18 +8547,18 @@ static void ixgbe_add_vxlan_port(struct net_device *dev, sa_family_t sa_family, if (sa_family == AF_INET6) return; - if (adapter->vxlan_port == new_port) + if (adapter->vxlan_port == port) return; if (adapter->vxlan_port) { netdev_info(dev, "Hit Max num of VXLAN ports, not adding port %d\n", - new_port); + ntohs(port)); return; } - adapter->vxlan_port = new_port; - IXGBE_WRITE_REG(hw, IXGBE_VXLANCTRL, new_port); + adapter->vxlan_port = port; + IXGBE_WRITE_REG(hw, IXGBE_VXLANCTRL, ntohs(port)); } /** @@ -8586,7 +8571,6 @@ static void ixgbe_del_vxlan_port(struct net_device *dev, sa_family_t sa_family, __be16 port) { struct ixgbe_adapter *adapter = netdev_priv(dev); - u16 new_port = ntohs(port); if (!(adapter->flags & IXGBE_FLAG_VXLAN_OFFLOAD_CAPABLE)) return; @@ -8594,9 +8578,9 @@ static void ixgbe_del_vxlan_port(struct net_device *dev, sa_family_t sa_family, if (sa_family == AF_INET6) return; - if (adapter->vxlan_port != new_port) { + if (adapter->vxlan_port != port) { netdev_info(dev, "Port %d was not found, not deleting\n", - new_port); + ntohs(port)); return; } @@ -9265,17 +9249,6 @@ skip_sriov: netdev->priv_flags |= IFF_UNICAST_FLT; netdev->priv_flags |= IFF_SUPP_NOFCS; -#ifdef CONFIG_IXGBE_VXLAN - switch (adapter->hw.mac.type) { - case ixgbe_mac_X550: - case ixgbe_mac_X550EM_x: - netdev->hw_enc_features |= NETIF_F_RXCSUM; - break; - default: - break; - } -#endif /* CONFIG_IXGBE_VXLAN */ - #ifdef CONFIG_IXGBE_DCB netdev->dcbnl_ops = &dcbnl_ops; #endif -- cgit From e2873d43f9c607e9d855b8ae120d5990ba1722df Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Mon, 25 Jan 2016 19:39:40 -0800 Subject: ixgbe: Fix ATR so that it correctly handles IPv6 extension headers The ATR code was assuming that it would be able to use tcp_hdr for every TCP frame that came through. However this isn't the case as it is possible for a frame to arrive that is TCP but sent through something like a raw socket. As a result the driver was setting up bad filters in which tcp_hdr was really pointing to the network header so the data was all invalid. In order to correct this I have added a bit of parsing logic that will determine the TCP header location based off of the network header and either the offset in the case of the IPv4 header, or a walk through the IPv6 extension headers until it encounters the header that indicates IPPROTO_TCP. In addition I have added checks to verify that the lowest protocol provided is recognized as IPv4 or IPv6 to help mitigate raw sockets using ETH_P_ALL from having ATR applied to them. Signed-off-by: Alexander Duyck Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 45 +++++++++++++-------------- 1 file changed, 21 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index f67c9a6429ac..ee81618bb9f0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -7558,8 +7558,10 @@ static void ixgbe_atr(struct ixgbe_ring *ring, struct ipv6hdr *ipv6; } hdr; struct tcphdr *th; + unsigned int hlen; struct sk_buff *skb; __be16 vlan_id; + int l4_proto; /* if ring doesn't have a interrupt vector, cannot perform ATR */ if (!q_vector) @@ -7571,10 +7573,14 @@ static void ixgbe_atr(struct ixgbe_ring *ring, ring->atr_count++; + /* currently only IPv4/IPv6 with TCP is supported */ + if ((first->protocol != htons(ETH_P_IP)) && + (first->protocol != htons(ETH_P_IPV6))) + return; + /* snag network header to get L4 type and address */ skb = first->skb; hdr.network = skb_network_header(skb); - th = tcp_hdr(skb); #ifdef CONFIG_IXGBE_VXLAN if (skb->encapsulation && first->protocol == htons(ETH_P_IP) && @@ -7583,43 +7589,34 @@ static void ixgbe_atr(struct ixgbe_ring *ring, /* verify the port is recognized as VXLAN */ if (adapter->vxlan_port && - udp_hdr(skb)->dest == adapter->vxlan_port) { + udp_hdr(skb)->dest == adapter->vxlan_port) hdr.network = skb_inner_network_header(skb); - th = inner_tcp_hdr(skb); - } } #endif /* CONFIG_IXGBE_VXLAN */ /* Currently only IPv4/IPv6 with TCP is supported */ switch (hdr.ipv4->version) { case IPVERSION: - if (hdr.ipv4->protocol != IPPROTO_TCP) - return; + /* access ihl as u8 to avoid unaligned access on ia64 */ + hlen = (hdr.network[0] & 0x0F) << 2; + l4_proto = hdr.ipv4->protocol; break; case 6: - if (likely((unsigned char *)th - hdr.network == - sizeof(struct ipv6hdr))) { - if (hdr.ipv6->nexthdr != IPPROTO_TCP) - return; - } else { - __be16 frag_off; - u8 l4_hdr; - - ipv6_skip_exthdr(skb, hdr.network - skb->data + - sizeof(struct ipv6hdr), - &l4_hdr, &frag_off); - if (unlikely(frag_off)) - return; - if (l4_hdr != IPPROTO_TCP) - return; - } + hlen = hdr.network - skb->data; + l4_proto = ipv6_find_hdr(skb, &hlen, IPPROTO_TCP, NULL, NULL); + hlen -= hdr.network - skb->data; break; default: return; } - /* skip this packet since it is invalid or the socket is closing */ - if (!th || th->fin) + if (l4_proto != IPPROTO_TCP) + return; + + th = (struct tcphdr *)(hdr.network + hlen); + + /* skip this packet since the socket is closing */ + if (th->fin) return; /* sample on all syn packets or once every atr sample count */ -- cgit From d90b5b0ec1c7a3099dee9c18071a5b714eb3de52 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Fri, 29 Jan 2016 14:44:29 -0800 Subject: ixgbe: Use udelay to avoid sleeping while atomic Use udelay instead of usleep_range because this can be called while a lock is held. Signed-off-by: Mark Rustad Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 87aca3f7c3de..68a9c646498e 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -355,7 +355,7 @@ static s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl) command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL); if (!(command & IXGBE_SB_IOSF_CTRL_BUSY)) break; - usleep_range(10, 20); + udelay(10); } if (ctrl) *ctrl = command; -- cgit From 6c211fe1e71e2bf7baa45a78ac5358a1f45a7fe9 Mon Sep 17 00:00:00 2001 From: Stefan Assmann Date: Wed, 3 Feb 2016 09:20:48 +0100 Subject: ixgbe: call ndo_stop() instead of dev_close() when running offline selftest Calling dev_close() causes IFF_UP to be cleared which will remove the interfaces routes and some addresses. That's probably not what the user intended when running the offline selftest. Besides this does not happen if the interface is brought down before the test, so the current behaviour is inconsistent. Instead call the net_device_ops ndo_stop function directly and avoid touching IFF_UP at all. Signed-off-by: Stefan Assmann Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 2 ++ drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 4 ++-- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 458549c06a4f..e4949af7dd6b 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -877,6 +877,8 @@ extern const char ixgbe_driver_version[]; extern char ixgbe_default_device_descr[]; #endif /* IXGBE_FCOE */ +int ixgbe_open(struct net_device *netdev); +int ixgbe_close(struct net_device *netdev); void ixgbe_up(struct ixgbe_adapter *adapter); void ixgbe_down(struct ixgbe_adapter *adapter); void ixgbe_reinit_locked(struct ixgbe_adapter *adapter); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index 726e0eeee63b..b3530e1e3ce1 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -2053,7 +2053,7 @@ static void ixgbe_diag_test(struct net_device *netdev, if (if_running) /* indicate we're in test mode */ - dev_close(netdev); + ixgbe_close(netdev); else ixgbe_reset(adapter); @@ -2091,7 +2091,7 @@ skip_loopback: /* clear testing bit and return adapter to previous state */ clear_bit(__IXGBE_TESTING, &adapter->state); if (if_running) - dev_open(netdev); + ixgbe_open(netdev); else if (hw->mac.ops.disable_tx_laser) hw->mac.ops.disable_tx_laser(hw); } else { diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index ee81618bb9f0..267a50747cbf 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -5992,7 +5992,7 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu) * handler is registered with the OS, the watchdog timer is started, * and the stack is notified that the interface is ready. **/ -static int ixgbe_open(struct net_device *netdev) +int ixgbe_open(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; @@ -6094,7 +6094,7 @@ static void ixgbe_close_suspend(struct ixgbe_adapter *adapter) * needs to be disabled. A global MAC reset is issued to stop the * hardware, and all transmit and receive resources are freed. **/ -static int ixgbe_close(struct net_device *netdev) +int ixgbe_close(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); -- cgit From 324d086709978fce1671ba04087bf90865b04398 Mon Sep 17 00:00:00 2001 From: Stefan Assmann Date: Wed, 3 Feb 2016 09:20:49 +0100 Subject: ixgbevf: call ndo_stop() instead of dev_close() when running offline selftest Calling dev_close() causes IFF_UP to be cleared which will remove the interfaces routes and some addresses. That's probably not what the user intended when running the offline selftest. Besides this does not happen if the interface is brought down before the test, so the current behaviour is inconsistent. Instead call the net_device_ops ndo_stop function directly and avoid touching IFF_UP at all. Signed-off-by: Stefan Assmann Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbevf/ethtool.c | 4 ++-- drivers/net/ethernet/intel/ixgbevf/ixgbevf.h | 2 ++ drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbevf/ethtool.c b/drivers/net/ethernet/intel/ixgbevf/ethtool.c index c48aef613b0a..d7aa4b203f40 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ethtool.c +++ b/drivers/net/ethernet/intel/ixgbevf/ethtool.c @@ -680,7 +680,7 @@ static void ixgbevf_diag_test(struct net_device *netdev, if (if_running) /* indicate we're in test mode */ - dev_close(netdev); + ixgbevf_close(netdev); else ixgbevf_reset(adapter); @@ -692,7 +692,7 @@ static void ixgbevf_diag_test(struct net_device *netdev, clear_bit(__IXGBEVF_TESTING, &adapter->state); if (if_running) - dev_open(netdev); + ixgbevf_open(netdev); } else { hw_dbg(&adapter->hw, "online testing starting\n"); /* Online tests */ diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h index 68ec7daa04fd..991eeae81473 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h @@ -486,6 +486,8 @@ extern const struct ixgbe_mbx_operations ixgbevf_mbx_ops; extern const char ixgbevf_driver_name[]; extern const char ixgbevf_driver_version[]; +int ixgbevf_open(struct net_device *netdev); +int ixgbevf_close(struct net_device *netdev); void ixgbevf_up(struct ixgbevf_adapter *adapter); void ixgbevf_down(struct ixgbevf_adapter *adapter); void ixgbevf_reinit_locked(struct ixgbevf_adapter *adapter); diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 0ea14c0a2e74..6a337bbf6820 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -3122,7 +3122,7 @@ static void ixgbevf_free_all_rx_resources(struct ixgbevf_adapter *adapter) * handler is registered with the OS, the watchdog timer is started, * and the stack is notified that the interface is ready. **/ -static int ixgbevf_open(struct net_device *netdev) +int ixgbevf_open(struct net_device *netdev) { struct ixgbevf_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; @@ -3205,7 +3205,7 @@ err_setup_reset: * needs to be disabled. A global MAC reset is issued to stop the * hardware, and all transmit and receive resources are freed. **/ -static int ixgbevf_close(struct net_device *netdev) +int ixgbevf_close(struct net_device *netdev) { struct ixgbevf_adapter *adapter = netdev_priv(netdev); -- cgit From 32ca68683532ab629d16cede1102b36ae5346f40 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Wed, 10 Feb 2016 15:16:30 -0800 Subject: ixgbevf: fix error code path when setting MAC address Return error when a MAC address change is rejected by the PF. This will prevent the user from modifying the MAC address when that operation is not permitted. Signed-off-by: Emil Tantilov Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 12 ++++++++---- drivers/net/ethernet/intel/ixgbevf/vf.c | 4 +++- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 6a337bbf6820..b0edae94d73d 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -3692,19 +3692,23 @@ static int ixgbevf_set_mac(struct net_device *netdev, void *p) struct ixgbevf_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; struct sockaddr *addr = p; + int err; if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - ether_addr_copy(netdev->dev_addr, addr->sa_data); - ether_addr_copy(hw->mac.addr, addr->sa_data); - spin_lock_bh(&adapter->mbx_lock); - hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0); + err = hw->mac.ops.set_rar(hw, 0, addr->sa_data, 0); spin_unlock_bh(&adapter->mbx_lock); + if (err) + return -EPERM; + + ether_addr_copy(hw->mac.addr, addr->sa_data); + ether_addr_copy(netdev->dev_addr, addr->sa_data); + return 0; } diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c b/drivers/net/ethernet/intel/ixgbevf/vf.c index 61a98f4c5746..4d613a4f2a7f 100644 --- a/drivers/net/ethernet/intel/ixgbevf/vf.c +++ b/drivers/net/ethernet/intel/ixgbevf/vf.c @@ -408,8 +408,10 @@ static s32 ixgbevf_set_rar_vf(struct ixgbe_hw *hw, u32 index, u8 *addr, /* if nacked the address was rejected, use "perm_addr" */ if (!ret_val && - (msgbuf[0] == (IXGBE_VF_SET_MAC_ADDR | IXGBE_VT_MSGTYPE_NACK))) + (msgbuf[0] == (IXGBE_VF_SET_MAC_ADDR | IXGBE_VT_MSGTYPE_NACK))) { ixgbevf_get_mac_addr_vf(hw, hw->mac.addr); + return IXGBE_ERR_MBX; + } return ret_val; } -- cgit From 6e2a60b57a83ea134c06c5226aaff20e7e9ce221 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Wed, 17 Feb 2016 15:55:06 -0800 Subject: ixgbe: make __ixgbe_setup_tc static This function is only used in ixgbe_main.c Resolves a "missing prototype" warning when building the driver with W=1 Reported-by: Phil Schmitt Signed-off-by: Emil Tantilov Acked-by: John Fastabend Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 267a50747cbf..f5736a3b252e 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -8376,8 +8376,8 @@ err_out: return -EINVAL; } -int __ixgbe_setup_tc(struct net_device *dev, u32 handle, __be16 proto, - struct tc_to_netdev *tc) +static int __ixgbe_setup_tc(struct net_device *dev, u32 handle, __be16 proto, + struct tc_to_netdev *tc) { struct ixgbe_adapter *adapter = netdev_priv(dev); -- cgit From 176621c964e9279c42c6b641688360e5cd0baedf Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Mon, 7 Mar 2016 09:41:47 -0800 Subject: ixgbe: fix error handling in TC cls_u32 offload routines Check for handle ids when adding/deleting hash nodes OR adding/deleting filter entries and limit them to max number of links or header nodes supported(IXGBE_MAX_LINK_HANDLE). Start from bit 0 when setting hash table bit-map.(adapter->tables) Signed-off-by: Sridhar Samudrala Acked-by: John Fastabend Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 52 +++++++++++++++++---------- 1 file changed, 34 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index f5736a3b252e..ca9c54341784 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -8192,10 +8192,17 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc) static int ixgbe_delete_clsu32(struct ixgbe_adapter *adapter, struct tc_cls_u32_offload *cls) { + u32 uhtid = TC_U32_USERHTID(cls->knode.handle); + u32 loc; int err; + if ((uhtid != 0x800) && (uhtid >= IXGBE_MAX_LINK_HANDLE)) + return -EINVAL; + + loc = cls->knode.handle & 0xfffff; + spin_lock(&adapter->fdir_perfect_lock); - err = ixgbe_update_ethtool_fdir_entry(adapter, NULL, cls->knode.handle); + err = ixgbe_update_ethtool_fdir_entry(adapter, NULL, loc); spin_unlock(&adapter->fdir_perfect_lock); return err; } @@ -8204,20 +8211,30 @@ static int ixgbe_configure_clsu32_add_hnode(struct ixgbe_adapter *adapter, __be16 protocol, struct tc_cls_u32_offload *cls) { + u32 uhtid = TC_U32_USERHTID(cls->hnode.handle); + + if (uhtid >= IXGBE_MAX_LINK_HANDLE) + return -EINVAL; + /* This ixgbe devices do not support hash tables at the moment * so abort when given hash tables. */ if (cls->hnode.divisor > 0) return -EINVAL; - set_bit(TC_U32_USERHTID(cls->hnode.handle), &adapter->tables); + set_bit(uhtid - 1, &adapter->tables); return 0; } static int ixgbe_configure_clsu32_del_hnode(struct ixgbe_adapter *adapter, struct tc_cls_u32_offload *cls) { - clear_bit(TC_U32_USERHTID(cls->hnode.handle), &adapter->tables); + u32 uhtid = TC_U32_USERHTID(cls->hnode.handle); + + if (uhtid >= IXGBE_MAX_LINK_HANDLE) + return -EINVAL; + + clear_bit(uhtid - 1, &adapter->tables); return 0; } @@ -8235,27 +8252,29 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter, #endif int i, err = 0; u8 queue; - u32 handle; + u32 uhtid, link_uhtid; memset(&mask, 0, sizeof(union ixgbe_atr_input)); - handle = cls->knode.handle; + uhtid = TC_U32_USERHTID(cls->knode.handle); + link_uhtid = TC_U32_USERHTID(cls->knode.link_handle); - /* At the moment cls_u32 jumps to transport layer and skips past + /* At the moment cls_u32 jumps to network layer and skips past * L2 headers. The canonical method to match L2 frames is to use * negative values. However this is error prone at best but really * just broken because there is no way to "know" what sort of hdr - * is in front of the transport layer. Fix cls_u32 to support L2 + * is in front of the network layer. Fix cls_u32 to support L2 * headers when needed. */ if (protocol != htons(ETH_P_IP)) return -EINVAL; - if (cls->knode.link_handle || - cls->knode.link_handle >= IXGBE_MAX_LINK_HANDLE) { + if (link_uhtid) { struct ixgbe_nexthdr *nexthdr = ixgbe_ipv4_jumps; - u32 uhtid = TC_U32_USERHTID(cls->knode.link_handle); - if (!test_bit(uhtid, &adapter->tables)) + if (link_uhtid >= IXGBE_MAX_LINK_HANDLE) + return -EINVAL; + + if (!test_bit(link_uhtid - 1, &adapter->tables)) return -EINVAL; for (i = 0; nexthdr[i].jump; i++) { @@ -8271,10 +8290,7 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter, nexthdr->mask != cls->knode.sel->keys[0].mask) return -EINVAL; - if (uhtid >= IXGBE_MAX_LINK_HANDLE) - return -EINVAL; - - adapter->jump_tables[uhtid] = nexthdr->jump; + adapter->jump_tables[link_uhtid] = nexthdr->jump; } return 0; } @@ -8291,13 +8307,13 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter, * To add support for new nodes update ixgbe_model.h parse structures * this function _should_ be generic try not to hardcode values here. */ - if (TC_U32_USERHTID(handle) == 0x800) { + if (uhtid == 0x800) { field_ptr = adapter->jump_tables[0]; } else { - if (TC_U32_USERHTID(handle) >= ARRAY_SIZE(adapter->jump_tables)) + if (uhtid >= IXGBE_MAX_LINK_HANDLE) return -EINVAL; - field_ptr = adapter->jump_tables[TC_U32_USERHTID(handle)]; + field_ptr = adapter->jump_tables[uhtid]; } if (!field_ptr) -- cgit From ebd83ad818d2d4502d5e343388000d5dc829b7a8 Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Mon, 7 Mar 2016 09:41:48 -0800 Subject: ixgbe: Fix cls_u32 offload support for fields with masks Remove the incorrect check for mask in ixgbe_configure_clsu32 and drop the 'mask' field that is not required in struct ixgbe_mat_field Verified with the following filters: #tc qdisc add dev p4p1 ingress #tc filter add dev p4p1 parent ffff: protocol ip prio 99 \ handle 800:0:1 u32 ht 800: \ match ip dst 10.0.0.1/8 match ip src 10.0.0.2/8 action drop #tc filter add dev p4p1 parent ffff: protocol ip prio 99 \ handle 800:0:2 u32 ht 800: \ match ip dst 11.0.0.1/16 match ip src 11.0.0.2/16 action drop #tc filter add dev p4p1 parent ffff: protocol ip prio 99 \ handle 800:0:3 u32 ht 800: \ match ip dst 12.0.0.1/24 match ip src 12.0.0.2/24 action drop #tc filter add dev p4p1 parent ffff: protocol ip prio 99 \ handle 800:0:4 u32 ht 800: \ match ip dst 13.0.0.1/32 match ip src 13.0.0.2/32 action drop Signed-off-by: Sridhar Samudrala Acked-by: John Fastabend Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 3 +-- drivers/net/ethernet/intel/ixgbe/ixgbe_model.h | 9 ++++----- 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index ca9c54341784..7df3fe29b210 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -8331,8 +8331,7 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter, int j; for (j = 0; field_ptr[j].val; j++) { - if (field_ptr[j].off == off && - field_ptr[j].mask == m) { + if (field_ptr[j].off == off) { field_ptr[j].val(input, &mask, val, m); input->filter.formatted.flow_type |= field_ptr[j].type; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_model.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_model.h index ce48872d4782..61f729073978 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_model.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_model.h @@ -32,7 +32,6 @@ struct ixgbe_mat_field { unsigned int off; - unsigned int mask; int (*val)(struct ixgbe_fdir_filter *input, union ixgbe_atr_input *mask, u32 val, u32 m); @@ -58,9 +57,9 @@ static inline int ixgbe_mat_prgm_dip(struct ixgbe_fdir_filter *input, } static struct ixgbe_mat_field ixgbe_ipv4_fields[] = { - { .off = 12, .mask = -1, .val = ixgbe_mat_prgm_sip, + { .off = 12, .val = ixgbe_mat_prgm_sip, .type = IXGBE_ATR_FLOW_TYPE_IPV4}, - { .off = 16, .mask = -1, .val = ixgbe_mat_prgm_dip, + { .off = 16, .val = ixgbe_mat_prgm_dip, .type = IXGBE_ATR_FLOW_TYPE_IPV4}, { .val = NULL } /* terminal node */ }; @@ -84,9 +83,9 @@ static inline int ixgbe_mat_prgm_dport(struct ixgbe_fdir_filter *input, }; static struct ixgbe_mat_field ixgbe_tcp_fields[] = { - {.off = 0, .mask = 0xffff, .val = ixgbe_mat_prgm_sport, + {.off = 0, .val = ixgbe_mat_prgm_sport, .type = IXGBE_ATR_FLOW_TYPE_TCPV4}, - {.off = 2, .mask = 0xffff, .val = ixgbe_mat_prgm_dport, + {.off = 2, .val = ixgbe_mat_prgm_dport, .type = IXGBE_ATR_FLOW_TYPE_TCPV4}, { .val = NULL } /* terminal node */ }; -- cgit From b5aea3de88e526a46839b7ccf049fab4f8ad7a4b Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Mon, 7 Mar 2016 09:41:49 -0800 Subject: ixgbe: Fix cls_u32 offload support for L4 ports Fix support for 16 bit source/dest port matches in ixgbe model. u32 uses a single 32-bit key value for both source and destination ports starting at offset 0. So replace the 2 functions with a single function that takes this key value/mask to program both source and dest ports. Verified with the following filter: #tc qdisc add dev p4p1 ingress #tc filter add dev p4p1 parent ffff: protocol ip prio 99 \ handle 1: u32 divisor 1 #tc filter add dev p4p1 parent ffff: protocol ip prio 99 \ handle 800:0:10 u32 ht 800: link 1: \ offset at 0 mask 0f00 shift 6 plus 0 eat match ip protocol 6 ff #tc filter add dev p4p1 parent ffff: protocol ip prio 99 \ handle 1:0:10 u32 ht 1: \ match tcp src 1024 ffff match tcp dst 80 ffff action drop #tc filter add dev p4p1 parent ffff: protocol ip prio 99 \ handle 1:0:11 u32 ht 1: \ match tcp src 1025 ffff action drop #tc filter add dev p4p1 parent ffff: protocol ip prio 99 \ handle 1:0:12 u32 ht 1: \ match tcp dst 81 ffff action drop Signed-off-by: Sridhar Samudrala Acked-by: John Fastabend Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_model.h | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_model.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_model.h index 61f729073978..74c53ad9d268 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_model.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_model.h @@ -64,28 +64,20 @@ static struct ixgbe_mat_field ixgbe_ipv4_fields[] = { { .val = NULL } /* terminal node */ }; -static inline int ixgbe_mat_prgm_sport(struct ixgbe_fdir_filter *input, +static inline int ixgbe_mat_prgm_ports(struct ixgbe_fdir_filter *input, union ixgbe_atr_input *mask, u32 val, u32 m) { input->filter.formatted.src_port = val & 0xffff; mask->formatted.src_port = m & 0xffff; - return 0; -}; + input->filter.formatted.dst_port = val >> 16; + mask->formatted.dst_port = m >> 16; -static inline int ixgbe_mat_prgm_dport(struct ixgbe_fdir_filter *input, - union ixgbe_atr_input *mask, - u32 val, u32 m) -{ - input->filter.formatted.dst_port = val & 0xffff; - mask->formatted.dst_port = m & 0xffff; return 0; }; static struct ixgbe_mat_field ixgbe_tcp_fields[] = { - {.off = 0, .val = ixgbe_mat_prgm_sport, - .type = IXGBE_ATR_FLOW_TYPE_TCPV4}, - {.off = 2, .val = ixgbe_mat_prgm_dport, + {.off = 0, .val = ixgbe_mat_prgm_ports, .type = IXGBE_ATR_FLOW_TYPE_TCPV4}, { .val = NULL } /* terminal node */ }; -- cgit From fd975a7b180c9a8f6e02d2251eaabe9b0dcfeed6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 9 Mar 2016 20:38:55 +0800 Subject: gpio: menz127: Drop lock field from struct men_z127_gpio Current code uses a uninitialized spin lock. bgpio_init() already initialized a spin lock, so let's switch to use &gc->bgpio_lock instead and remove the lock from struct men_z127_gpio. Fixes: f436bc2726c6 "gpio: add driver for MEN 16Z127 GPIO controller" Signed-off-by: Axel Lin Signed-off-by: Linus Walleij --- drivers/gpio/gpio-menz127.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-menz127.c b/drivers/gpio/gpio-menz127.c index a68e199d579d..c5c9599a3a71 100644 --- a/drivers/gpio/gpio-menz127.c +++ b/drivers/gpio/gpio-menz127.c @@ -37,7 +37,6 @@ struct men_z127_gpio { void __iomem *reg_base; struct mcb_device *mdev; struct resource *mem; - spinlock_t lock; }; static int men_z127_debounce(struct gpio_chip *gc, unsigned gpio, @@ -69,7 +68,7 @@ static int men_z127_debounce(struct gpio_chip *gc, unsigned gpio, debounce /= 50; } - spin_lock(&priv->lock); + spin_lock(&gc->bgpio_lock); db_en = readl(priv->reg_base + MEN_Z127_DBER); @@ -84,7 +83,7 @@ static int men_z127_debounce(struct gpio_chip *gc, unsigned gpio, writel(db_en, priv->reg_base + MEN_Z127_DBER); writel(db_cnt, priv->reg_base + GPIO_TO_DBCNT_REG(gpio)); - spin_unlock(&priv->lock); + spin_unlock(&gc->bgpio_lock); return 0; } @@ -97,7 +96,7 @@ static int men_z127_request(struct gpio_chip *gc, unsigned gpio_pin) if (gpio_pin >= gc->ngpio) return -EINVAL; - spin_lock(&priv->lock); + spin_lock(&gc->bgpio_lock); od_en = readl(priv->reg_base + MEN_Z127_ODER); if (gpiochip_line_is_open_drain(gc, gpio_pin)) @@ -106,7 +105,7 @@ static int men_z127_request(struct gpio_chip *gc, unsigned gpio_pin) od_en &= ~BIT(gpio_pin); writel(od_en, priv->reg_base + MEN_Z127_ODER); - spin_unlock(&priv->lock); + spin_unlock(&gc->bgpio_lock); return 0; } -- cgit From 8d8ee18cc707f498b6dad18915576f23b00bcff8 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 21 Mar 2016 20:03:50 +0800 Subject: gpio: xgene: Prevent NULL pointer dereference platform_get_resource() can return NULL, thus add NULL test to prevent NULL pointer dereference. Signed-off-by: Axel Lin Signed-off-by: Linus Walleij --- drivers/gpio/gpio-xgene.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/gpio/gpio-xgene.c b/drivers/gpio/gpio-xgene.c index c0aa387664bf..0dc916191689 100644 --- a/drivers/gpio/gpio-xgene.c +++ b/drivers/gpio/gpio-xgene.c @@ -173,6 +173,11 @@ static int xgene_gpio_probe(struct platform_device *pdev) } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + err = -EINVAL; + goto err; + } + gpio->base = devm_ioremap_nocache(&pdev->dev, res->start, resource_size(res)); if (!gpio->base) { -- cgit From fea24857bb62990b839feb62090ad72a1c93735a Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 29 Mar 2016 18:00:50 +0100 Subject: qed: initialize return rc to avoid returning garbage in the case where qed_slowpath_irq_req is not called, rc is not assigned and so qed_int_igu_enable will return a garbage value. Fix this by initializing rc to 0. Signed-off-by: Colin Ian King Acked-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_int.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.c b/drivers/net/ethernet/qlogic/qed/qed_int.c index ffd0accc2ec9..2017b0121f5f 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_int.c +++ b/drivers/net/ethernet/qlogic/qed/qed_int.c @@ -2750,7 +2750,7 @@ void qed_int_igu_enable_int(struct qed_hwfn *p_hwfn, int qed_int_igu_enable(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, enum qed_int_mode int_mode) { - int rc; + int rc = 0; /* Configure AEU signal change to produce attentions */ qed_wr(p_hwfn, p_ptt, IGU_REG_ATTENTION_ENABLE, 0); -- cgit From cb41c997d4446b39dd03b8a74196125739d7c3ac Mon Sep 17 00:00:00 2001 From: Xin Long Date: Wed, 30 Mar 2016 10:58:39 +0800 Subject: team: team should sync the port's uc/mc addrs when add a port There is an issue when we use mavtap over team: When we replug nic links from team0, the real nics's mc list will not include the maddr for macvtap any more. then we can't receive pkts to macvtap device, as they are filterred by mc list of nic. In Bonding Driver, it syncs the uc/mc addrs in bond_enslave(). We will fix this issue on team by adding the port's uc/mc addrs sync in team_port_add. Signed-off-by: Xin Long Signed-off-by: David S. Miller --- drivers/net/team/team.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 26c64d2782fa..a0f64cba86ba 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -1198,6 +1198,9 @@ static int team_port_add(struct team *team, struct net_device *port_dev) goto err_dev_open; } + dev_uc_sync_multiple(port_dev, dev); + dev_mc_sync_multiple(port_dev, dev); + err = vlan_vids_add_by_dev(port_dev, dev); if (err) { netdev_err(dev, "Failed to add vlan ids to device %s\n", @@ -1261,6 +1264,8 @@ err_enable_netpoll: vlan_vids_del_by_dev(port_dev, dev); err_vids_add: + dev_uc_unsync(port_dev, dev); + dev_mc_unsync(port_dev, dev); dev_close(port_dev); err_dev_open: -- cgit From 33e52d888d0c84a0c66f13357a53113fd9710bd6 Mon Sep 17 00:00:00 2001 From: Prashant Sreedharan Date: Mon, 28 Mar 2016 19:46:04 -0400 Subject: bnxt_en: Initialize CP doorbell value before ring allocation The existing code does the following: allocate completion ring initialize completion ring doorbell disable interrupts on this completion ring by writing to the doorbell We can have a race where firmware sends an asynchronous event to the host after completion ring allocation and before doorbell is initialized. When this happens driver can crash while ringing the doorbell using uninitialized value as part of handling the IRQ/napi request. Signed-off-by: Prashant Sreedharan Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index aabbd51db981..c92053c8b2cc 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -3391,11 +3391,11 @@ static int bnxt_hwrm_ring_alloc(struct bnxt *bp) struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; struct bnxt_ring_struct *ring = &cpr->cp_ring_struct; + cpr->cp_doorbell = bp->bar1 + i * 0x80; rc = hwrm_ring_alloc_send_msg(bp, ring, HWRM_RING_ALLOC_CMPL, i, INVALID_STATS_CTX_ID); if (rc) goto err_out; - cpr->cp_doorbell = bp->bar1 + i * 0x80; BNXT_CP_DB(cpr->cp_doorbell, cpr->cp_raw_cons); bp->grp_info[i].cp_fw_ring_id = ring->fw_ring_id; } -- cgit From e6ef26991a46e20879bebb8298080eb7ceed4ae8 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 28 Mar 2016 19:46:05 -0400 Subject: bnxt_en: Implement proper firmware message padding. The size of every padded firmware message is specified in the first HWRM_VER_GET response message. Use this value to pad every message after that. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 6 +++++- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index c92053c8b2cc..4600a05a1d7d 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -2653,7 +2653,7 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len, /* Write request msg to hwrm channel */ __iowrite32_copy(bp->bar0, data, msg_len / 4); - for (i = msg_len; i < HWRM_MAX_REQ_LEN; i += 4) + for (i = msg_len; i < BNXT_HWRM_MAX_REQ_LEN; i += 4) writel(0, bp->bar0 + i); /* currently supports only one outstanding message */ @@ -3830,6 +3830,7 @@ static int bnxt_hwrm_ver_get(struct bnxt *bp) struct hwrm_ver_get_input req = {0}; struct hwrm_ver_get_output *resp = bp->hwrm_cmd_resp_addr; + bp->hwrm_max_req_len = HWRM_MAX_REQ_LEN; bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VER_GET, -1, -1); req.hwrm_intf_maj = HWRM_VERSION_MAJOR; req.hwrm_intf_min = HWRM_VERSION_MINOR; @@ -3855,6 +3856,9 @@ static int bnxt_hwrm_ver_get(struct bnxt *bp) if (!bp->hwrm_cmd_timeout) bp->hwrm_cmd_timeout = DFLT_HWRM_CMD_TIMEOUT; + if (resp->hwrm_intf_maj >= 1) + bp->hwrm_max_req_len = le16_to_cpu(resp->max_req_win_len); + hwrm_ver_get_exit: mutex_unlock(&bp->hwrm_cmd_lock); return rc; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index ec04c47172b7..709b95b8fcba 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -477,6 +477,7 @@ struct rx_tpa_end_cmp_ext { #define RING_CMP(idx) ((idx) & bp->cp_ring_mask) #define NEXT_CMP(idx) RING_CMP(ADV_RAW_CMP(idx, 1)) +#define BNXT_HWRM_MAX_REQ_LEN (bp->hwrm_max_req_len) #define DFLT_HWRM_CMD_TIMEOUT 500 #define HWRM_CMD_TIMEOUT (bp->hwrm_cmd_timeout) #define HWRM_RESET_TIMEOUT ((HWRM_CMD_TIMEOUT) * 4) @@ -953,6 +954,7 @@ struct bnxt { dma_addr_t hw_tx_port_stats_map; int hw_port_stats_size; + u16 hwrm_max_req_len; int hwrm_cmd_timeout; struct mutex hwrm_cmd_lock; /* serialize hwrm messages */ struct hwrm_ver_get_output ver_resp; -- cgit From 49b5c7a125201bb42c25831fda3a50305c29ef50 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 28 Mar 2016 19:46:06 -0400 Subject: bnxt_en: Fix typo in bnxt_hwrm_set_pause_common(). The typo caused the wrong flow control bit to be set. Reported by: Ajit Khaparde Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 4600a05a1d7d..12a009d720cd 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -4559,7 +4559,7 @@ bnxt_hwrm_set_pause_common(struct bnxt *bp, struct hwrm_port_phy_cfg_input *req) if (bp->link_info.req_flow_ctrl & BNXT_LINK_PAUSE_RX) req->auto_pause |= PORT_PHY_CFG_REQ_AUTO_PAUSE_RX; if (bp->link_info.req_flow_ctrl & BNXT_LINK_PAUSE_TX) - req->auto_pause |= PORT_PHY_CFG_REQ_AUTO_PAUSE_RX; + req->auto_pause |= PORT_PHY_CFG_REQ_AUTO_PAUSE_TX; req->enables |= cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_AUTO_PAUSE); } else { -- cgit From 3c02d1bb32347d0674714ee170772d771d513469 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 28 Mar 2016 19:46:07 -0400 Subject: bnxt_en: Fix ethtool -a reporting. To report flow control tx/rx settings accurately regardless of autoneg setting, we should use link_info->req_flow_ctrl. Before this patch, the reported settings were only correct when autoneg was on. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index 9ada1662b651..2e472f6dbf2d 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -855,10 +855,8 @@ static void bnxt_get_pauseparam(struct net_device *dev, if (BNXT_VF(bp)) return; epause->autoneg = !!(link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL); - epause->rx_pause = - ((link_info->auto_pause_setting & BNXT_LINK_PAUSE_RX) != 0); - epause->tx_pause = - ((link_info->auto_pause_setting & BNXT_LINK_PAUSE_TX) != 0); + epause->rx_pause = !!(link_info->req_flow_ctrl & BNXT_LINK_PAUSE_RX); + epause->tx_pause = !!(link_info->req_flow_ctrl & BNXT_LINK_PAUSE_TX); } static int bnxt_set_pauseparam(struct net_device *dev, -- cgit From 572a143489a10360ce2aca98c64f8be43c8400a6 Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Wed, 24 Feb 2016 19:24:09 +0200 Subject: iser-target: Use ib_drain_qp Now the rdma core offers a QP draining service in v4.6-rc1, use it instead of our own. Signed-off-by: Sagi Grimberg Reported-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/infiniband/ulp/isert/ib_isert.c | 39 ++++----------------------------- drivers/infiniband/ulp/isert/ib_isert.h | 2 -- 2 files changed, 4 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 60b30d338a81..411e4464ca23 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -63,7 +63,6 @@ isert_rdma_accept(struct isert_conn *isert_conn); struct rdma_cm_id *isert_setup_id(struct isert_np *isert_np); static void isert_release_work(struct work_struct *work); -static void isert_wait4flush(struct isert_conn *isert_conn); static void isert_recv_done(struct ib_cq *cq, struct ib_wc *wc); static void isert_send_done(struct ib_cq *cq, struct ib_wc *wc); static void isert_login_recv_done(struct ib_cq *cq, struct ib_wc *wc); @@ -141,7 +140,7 @@ isert_create_qp(struct isert_conn *isert_conn, attr.qp_context = isert_conn; attr.send_cq = comp->cq; attr.recv_cq = comp->cq; - attr.cap.max_send_wr = ISERT_QP_MAX_REQ_DTOS; + attr.cap.max_send_wr = ISERT_QP_MAX_REQ_DTOS + 1; attr.cap.max_recv_wr = ISERT_QP_MAX_RECV_DTOS + 1; attr.cap.max_send_sge = device->ib_device->attrs.max_sge; isert_conn->max_sge = min(device->ib_device->attrs.max_sge, @@ -887,7 +886,7 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id, break; case ISER_CONN_UP: isert_conn_terminate(isert_conn); - isert_wait4flush(isert_conn); + ib_drain_qp(isert_conn->qp); isert_handle_unbound_conn(isert_conn); break; case ISER_CONN_BOUND: @@ -3213,36 +3212,6 @@ isert_wait4cmds(struct iscsi_conn *conn) } } -static void -isert_beacon_done(struct ib_cq *cq, struct ib_wc *wc) -{ - struct isert_conn *isert_conn = wc->qp->qp_context; - - isert_print_wc(wc, "beacon"); - - isert_info("conn %p completing wait_comp_err\n", isert_conn); - complete(&isert_conn->wait_comp_err); -} - -static void -isert_wait4flush(struct isert_conn *isert_conn) -{ - struct ib_recv_wr *bad_wr; - static struct ib_cqe cqe = { .done = isert_beacon_done }; - - isert_info("conn %p\n", isert_conn); - - init_completion(&isert_conn->wait_comp_err); - isert_conn->beacon.wr_cqe = &cqe; - /* post an indication that all flush errors were consumed */ - if (ib_post_recv(isert_conn->qp, &isert_conn->beacon, &bad_wr)) { - isert_err("conn %p failed to post beacon", isert_conn); - return; - } - - wait_for_completion(&isert_conn->wait_comp_err); -} - /** * isert_put_unsol_pending_cmds() - Drop commands waiting for * unsolicitate dataout @@ -3288,7 +3257,7 @@ static void isert_wait_conn(struct iscsi_conn *conn) isert_conn_terminate(isert_conn); mutex_unlock(&isert_conn->mutex); - isert_wait4flush(isert_conn); + ib_drain_qp(isert_conn->qp); isert_put_unsol_pending_cmds(conn); isert_wait4cmds(conn); isert_wait4logout(isert_conn); @@ -3300,7 +3269,7 @@ static void isert_free_conn(struct iscsi_conn *conn) { struct isert_conn *isert_conn = conn->context; - isert_wait4flush(isert_conn); + ib_drain_qp(isert_conn->qp); isert_put_conn(isert_conn); } diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h index 192788a4820c..147900cbb578 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.h +++ b/drivers/infiniband/ulp/isert/ib_isert.h @@ -209,14 +209,12 @@ struct isert_conn { struct ib_qp *qp; struct isert_device *device; struct mutex mutex; - struct completion wait_comp_err; struct kref kref; struct list_head fr_pool; int fr_pool_size; /* lock to protect fastreg pool */ spinlock_t pool_lock; struct work_struct release_work; - struct ib_recv_wr beacon; bool logout_posted; bool snd_w_inv; }; -- cgit From ce7043fd903eb9722a885b98b53fffe2cedfb047 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 29 Mar 2016 13:03:33 +0200 Subject: target: remove ->fabric_cleanup_nodeacl Instead we can clean up the list of default ACLs in core code. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_configfs.c | 9 --------- drivers/target/target_core_fabric_configfs.c | 4 +--- 2 files changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index a24443ba59ea..3c05d1e97f8f 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -779,14 +779,6 @@ static int lio_target_init_nodeacl(struct se_node_acl *se_nacl, return 0; } -static void lio_target_cleanup_nodeacl( struct se_node_acl *se_nacl) -{ - struct iscsi_node_acl *acl = container_of(se_nacl, - struct iscsi_node_acl, se_node_acl); - - configfs_remove_default_groups(&acl->se_node_acl.acl_fabric_stat_group); -} - /* End items for lio_target_acl_cit */ /* Start items for lio_target_tpg_attrib_cit */ @@ -1665,7 +1657,6 @@ const struct target_core_fabric_ops iscsi_ops = { .fabric_make_np = lio_target_call_addnptotpg, .fabric_drop_np = lio_target_call_delnpfromtpg, .fabric_init_nodeacl = lio_target_init_nodeacl, - .fabric_cleanup_nodeacl = lio_target_cleanup_nodeacl, .tfc_discovery_attrs = lio_target_discovery_auth_attrs, .tfc_wwn_attrs = lio_target_wwn_attrs, diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index 1bd5c72b663e..096790ad6e50 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -338,10 +338,8 @@ static void target_fabric_nacl_base_release(struct config_item *item) { struct se_node_acl *se_nacl = container_of(to_config_group(item), struct se_node_acl, acl_group); - struct target_fabric_configfs *tf = se_nacl->se_tpg->se_tpg_wwn->wwn_tf; - if (tf->tf_ops->fabric_cleanup_nodeacl) - tf->tf_ops->fabric_cleanup_nodeacl(se_nacl); + configfs_remove_default_groups(&se_nacl->acl_fabric_stat_group); core_tpg_del_initiator_node_acl(se_nacl); } -- cgit From e6e202edf000004422a901dfa301d600e32f17e3 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 29 Mar 2016 13:03:34 +0200 Subject: target: initialize the nacl base CIT begfore init_nodeacl The iSCSI targets wants to add a default group, for which we need to have the list of default groups initialized previously. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_fabric_configfs.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index 096790ad6e50..5991a4f816d8 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -381,14 +381,6 @@ static struct config_group *target_fabric_make_nodeacl( if (IS_ERR(se_nacl)) return ERR_CAST(se_nacl); - if (tf->tf_ops->fabric_init_nodeacl) { - int ret = tf->tf_ops->fabric_init_nodeacl(se_nacl, name); - if (ret) { - core_tpg_del_initiator_node_acl(se_nacl); - return ERR_PTR(ret); - } - } - config_group_init_type_name(&se_nacl->acl_group, name, &tf->tf_tpg_nacl_base_cit); @@ -412,6 +404,15 @@ static struct config_group *target_fabric_make_nodeacl( configfs_add_default_group(&se_nacl->acl_fabric_stat_group, &se_nacl->acl_group); + if (tf->tf_ops->fabric_init_nodeacl) { + int ret = tf->tf_ops->fabric_init_nodeacl(se_nacl, name); + if (ret) { + configfs_remove_default_groups(&se_nacl->acl_fabric_stat_group); + core_tpg_del_initiator_node_acl(se_nacl); + return ERR_PTR(ret); + } + } + return &se_nacl->acl_group; } -- cgit From 839559e10601ed4459c802cbfb69747bf1844078 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 29 Mar 2016 13:03:35 +0200 Subject: target: add a new add_wwn_groups fabrics method We need to have the WWN fully initialized before addig default groups to it, so add a new method to add these groups after the WWN has been initialized. Also remove the default groups in the core while we're at it. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_configfs.c | 19 +++++++++++-------- drivers/target/target_core_fabric_configfs.c | 3 +++ 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index 3c05d1e97f8f..97e5b69e0668 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -1239,6 +1239,16 @@ static struct se_wwn *lio_target_call_coreaddtiqn( if (IS_ERR(tiqn)) return ERR_CAST(tiqn); + pr_debug("LIO_Target_ConfigFS: REGISTER -> %s\n", tiqn->tiqn); + pr_debug("LIO_Target_ConfigFS: REGISTER -> Allocated Node:" + " %s\n", name); + return &tiqn->tiqn_wwn; +} + +static void lio_target_add_wwn_groups(struct se_wwn *wwn) +{ + struct iscsi_tiqn *tiqn = container_of(wwn, struct iscsi_tiqn, tiqn_wwn); + config_group_init_type_name(&tiqn->tiqn_stat_grps.iscsi_instance_group, "iscsi_instance", &iscsi_stat_instance_cit); configfs_add_default_group(&tiqn->tiqn_stat_grps.iscsi_instance_group, @@ -1263,12 +1273,6 @@ static struct se_wwn *lio_target_call_coreaddtiqn( "iscsi_logout_stats", &iscsi_stat_logout_cit); configfs_add_default_group(&tiqn->tiqn_stat_grps.iscsi_logout_stats_group, &tiqn->tiqn_wwn.fabric_stat_group); - - - pr_debug("LIO_Target_ConfigFS: REGISTER -> %s\n", tiqn->tiqn); - pr_debug("LIO_Target_ConfigFS: REGISTER -> Allocated Node:" - " %s\n", name); - return &tiqn->tiqn_wwn; } static void lio_target_call_coredeltiqn( @@ -1276,8 +1280,6 @@ static void lio_target_call_coredeltiqn( { struct iscsi_tiqn *tiqn = container_of(wwn, struct iscsi_tiqn, tiqn_wwn); - configfs_remove_default_groups(&tiqn->tiqn_wwn.fabric_stat_group); - pr_debug("LIO_Target_ConfigFS: DEREGISTER -> %s\n", tiqn->tiqn); iscsit_del_tiqn(tiqn); @@ -1652,6 +1654,7 @@ const struct target_core_fabric_ops iscsi_ops = { .aborted_task = lio_aborted_task, .fabric_make_wwn = lio_target_call_coreaddtiqn, .fabric_drop_wwn = lio_target_call_coredeltiqn, + .add_wwn_groups = lio_target_add_wwn_groups, .fabric_make_tpg = lio_target_tiqn_addtpg, .fabric_drop_tpg = lio_target_tiqn_deltpg, .fabric_make_np = lio_target_call_addnptotpg, diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index 5991a4f816d8..31a096aa16ab 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -891,6 +891,7 @@ static void target_fabric_release_wwn(struct config_item *item) struct se_wwn, wwn_group); struct target_fabric_configfs *tf = wwn->wwn_tf; + configfs_remove_default_groups(&wwn->fabric_stat_group); tf->tf_ops->fabric_drop_wwn(wwn); } @@ -944,6 +945,8 @@ static struct config_group *target_fabric_make_wwn( &tf->tf_wwn_fabric_stats_cit); configfs_add_default_group(&wwn->fabric_stat_group, &wwn->wwn_group); + if (tf->tf_ops->add_wwn_groups) + tf->tf_ops->add_wwn_groups(wwn); return &wwn->wwn_group; } -- cgit From 75baacf00fb471c3b01e604357ab53da7cf72dd4 Mon Sep 17 00:00:00 2001 From: Patrick Uiterwijk Date: Wed, 30 Mar 2016 01:39:40 +0000 Subject: net: dsa: mv88e6xxx: Introduce _mv88e6xxx_phy_page_{read, write} Add versions of the phy_page_read and _write functions to be used in a context where the SMI mutex is held. Tested-by: Vivien Didelot Reviewed-by: Vivien Didelot Signed-off-by: Patrick Uiterwijk Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 49 +++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index fa086e09d6b7..86a202975c02 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -2264,6 +2264,38 @@ static void mv88e6xxx_bridge_work(struct work_struct *work) mutex_unlock(&ps->smi_mutex); } +static int _mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page, + int reg, int val) +{ + int ret; + + ret = _mv88e6xxx_phy_write_indirect(ds, port, 0x16, page); + if (ret < 0) + goto restore_page_0; + + ret = _mv88e6xxx_phy_write_indirect(ds, port, reg, val); +restore_page_0: + _mv88e6xxx_phy_write_indirect(ds, port, 0x16, 0x0); + + return ret; +} + +static int _mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, + int reg) +{ + int ret; + + ret = _mv88e6xxx_phy_write_indirect(ds, port, 0x16, page); + if (ret < 0) + goto restore_page_0; + + ret = _mv88e6xxx_phy_read_indirect(ds, port, reg); +restore_page_0: + _mv88e6xxx_phy_write_indirect(ds, port, 0x16, 0x0); + + return ret; +} + static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); @@ -2714,13 +2746,9 @@ int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg) int ret; mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_phy_write_indirect(ds, port, 0x16, page); - if (ret < 0) - goto error; - ret = _mv88e6xxx_phy_read_indirect(ds, port, reg); -error: - _mv88e6xxx_phy_write_indirect(ds, port, 0x16, 0x0); + ret = _mv88e6xxx_phy_page_read(ds, port, page, reg); mutex_unlock(&ps->smi_mutex); + return ret; } @@ -2731,14 +2759,9 @@ int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page, int ret; mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_phy_write_indirect(ds, port, 0x16, page); - if (ret < 0) - goto error; - - ret = _mv88e6xxx_phy_write_indirect(ds, port, reg, val); -error: - _mv88e6xxx_phy_write_indirect(ds, port, 0x16, 0x0); + ret = _mv88e6xxx_phy_page_write(ds, port, page, reg, val); mutex_unlock(&ps->smi_mutex); + return ret; } -- cgit From 13a7ebb38a659254e71a4a95cf39429a9287912b Mon Sep 17 00:00:00 2001 From: Patrick Uiterwijk Date: Wed, 30 Mar 2016 01:39:41 +0000 Subject: net: dsa: mv88e6xxx: Clear the PDOWN bit on setup Some of the vendor-specific bootloaders set up this part of the initialization for us, so this was never added. However, since upstream bootloaders don't initialize the chip specifically, they leave the fiber MII's PDOWN flag set, which means that the CPU port doesn't connect. This patch checks whether this flag has been clear prior by something else, and if not make us clear it. Reviewed-by: Andrew Lunn Signed-off-by: Patrick Uiterwijk Tested-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 36 ++++++++++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx.h | 8 ++++++++ 2 files changed, 44 insertions(+) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 86a202975c02..50454be86570 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -2296,6 +2296,25 @@ restore_page_0: return ret; } +static int mv88e6xxx_power_on_serdes(struct dsa_switch *ds) +{ + int ret; + + ret = _mv88e6xxx_phy_page_read(ds, REG_FIBER_SERDES, PAGE_FIBER_SERDES, + MII_BMCR); + if (ret < 0) + return ret; + + if (ret & BMCR_PDOWN) { + ret &= ~BMCR_PDOWN; + ret = _mv88e6xxx_phy_page_write(ds, REG_FIBER_SERDES, + PAGE_FIBER_SERDES, MII_BMCR, + ret); + } + + return ret; +} + static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); @@ -2399,6 +2418,23 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) goto abort; } + /* If this port is connected to a SerDes, make sure the SerDes is not + * powered down. + */ + if (mv88e6xxx_6352_family(ds)) { + ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_STATUS); + if (ret < 0) + goto abort; + ret &= PORT_STATUS_CMODE_MASK; + if ((ret == PORT_STATUS_CMODE_100BASE_X) || + (ret == PORT_STATUS_CMODE_1000BASE_X) || + (ret == PORT_STATUS_CMODE_SGMII)) { + ret = mv88e6xxx_power_on_serdes(ds); + if (ret < 0) + goto abort; + } + } + /* Port Control 2: don't force a good FCS, set the maximum frame size to * 10240 bytes, disable 802.1q tags checking, don't discard tagged or * untagged frames on this port, do a destination address lookup on all diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 9a038aba48fb..26a424acd10f 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -28,6 +28,10 @@ #define SMI_CMD_OP_45_READ_DATA_INC ((3 << 10) | SMI_CMD_BUSY) #define SMI_DATA 0x01 +/* Fiber/SERDES Registers are located at SMI address F, page 1 */ +#define REG_FIBER_SERDES 0x0f +#define PAGE_FIBER_SERDES 0x01 + #define REG_PORT(p) (0x10 + (p)) #define PORT_STATUS 0x00 #define PORT_STATUS_PAUSE_EN BIT(15) @@ -45,6 +49,10 @@ #define PORT_STATUS_MGMII BIT(6) /* 6185 */ #define PORT_STATUS_TX_PAUSED BIT(5) #define PORT_STATUS_FLOW_CTRL BIT(4) +#define PORT_STATUS_CMODE_MASK 0x0f +#define PORT_STATUS_CMODE_100BASE_X 0x8 +#define PORT_STATUS_CMODE_1000BASE_X 0x9 +#define PORT_STATUS_CMODE_SGMII 0xa #define PORT_PCS_CTRL 0x01 #define PORT_PCS_CTRL_RGMII_DELAY_RXCLK BIT(15) #define PORT_PCS_CTRL_RGMII_DELAY_TXCLK BIT(14) -- cgit From b7854efce20be7c7bcd43424dee027124e9af27f Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Wed, 30 Mar 2016 19:53:41 +0800 Subject: net: mvpp2: replace MVPP2_CPU_D_CACHE_LINE_SIZE with L1_CACHE_BYTES The mvpp2 ip maybe used in SoCs which may have have 64bytes cacheline size. Replace the MVPP2_CPU_D_CACHE_LINE_SIZE with L1_CACHE_BYTES. And since dma_alloc_coherent() is always cacheline size aligned, so remove the align checks. Signed-off-by: Jisheng Zhang Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c index c797971aefab..05f358b81791 100644 --- a/drivers/net/ethernet/marvell/mvpp2.c +++ b/drivers/net/ethernet/marvell/mvpp2.c @@ -321,7 +321,6 @@ /* Lbtd 802.3 type */ #define MVPP2_IP_LBDT_TYPE 0xfffa -#define MVPP2_CPU_D_CACHE_LINE_SIZE 32 #define MVPP2_TX_CSUM_MAX_SIZE 9800 /* Timeout constants */ @@ -377,7 +376,7 @@ #define MVPP2_RX_PKT_SIZE(mtu) \ ALIGN((mtu) + MVPP2_MH_SIZE + MVPP2_VLAN_TAG_LEN + \ - ETH_HLEN + ETH_FCS_LEN, MVPP2_CPU_D_CACHE_LINE_SIZE) + ETH_HLEN + ETH_FCS_LEN, L1_CACHE_BYTES) #define MVPP2_RX_BUF_SIZE(pkt_size) ((pkt_size) + NET_SKB_PAD) #define MVPP2_RX_TOTAL_SIZE(buf_size) ((buf_size) + MVPP2_SKB_SHINFO_SIZE) @@ -4493,10 +4492,6 @@ static int mvpp2_aggr_txq_init(struct platform_device *pdev, if (!aggr_txq->descs) return -ENOMEM; - /* Make sure descriptor address is cache line size aligned */ - BUG_ON(aggr_txq->descs != - PTR_ALIGN(aggr_txq->descs, MVPP2_CPU_D_CACHE_LINE_SIZE)); - aggr_txq->last_desc = aggr_txq->size - 1; /* Aggr TXQ no reset WA */ @@ -4526,9 +4521,6 @@ static int mvpp2_rxq_init(struct mvpp2_port *port, if (!rxq->descs) return -ENOMEM; - BUG_ON(rxq->descs != - PTR_ALIGN(rxq->descs, MVPP2_CPU_D_CACHE_LINE_SIZE)); - rxq->last_desc = rxq->size - 1; /* Zero occupied and non-occupied counters - direct access */ @@ -4616,10 +4608,6 @@ static int mvpp2_txq_init(struct mvpp2_port *port, if (!txq->descs) return -ENOMEM; - /* Make sure descriptor address is cache line size aligned */ - BUG_ON(txq->descs != - PTR_ALIGN(txq->descs, MVPP2_CPU_D_CACHE_LINE_SIZE)); - txq->last_desc = txq->size - 1; /* Set Tx descriptors queue starting address - indirect access */ -- cgit From 9bd9ddb7f89edae241d2da78e3119f226b9b0cf6 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Wed, 30 Mar 2016 19:55:21 +0800 Subject: net: mvneta: replace MVNETA_CPU_D_CACHE_LINE_SIZE with L1_CACHE_BYTES The mvneta is also used in some Marvell berlin family SoCs which may have 64bytes cacheline size. Replace the MVNETA_CPU_D_CACHE_LINE_SIZE usage with L1_CACHE_BYTES. And since dma_alloc_coherent() is always cacheline size aligned, so remove the align checks. Signed-off-by: Jisheng Zhang Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvneta.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 577f7ca7deba..58808718d114 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -260,7 +260,6 @@ #define MVNETA_VLAN_TAG_LEN 4 -#define MVNETA_CPU_D_CACHE_LINE_SIZE 32 #define MVNETA_TX_CSUM_DEF_SIZE 1600 #define MVNETA_TX_CSUM_MAX_SIZE 9800 #define MVNETA_ACC_MODE_EXT1 1 @@ -300,7 +299,7 @@ #define MVNETA_RX_PKT_SIZE(mtu) \ ALIGN((mtu) + MVNETA_MH_SIZE + MVNETA_VLAN_TAG_LEN + \ ETH_HLEN + ETH_FCS_LEN, \ - MVNETA_CPU_D_CACHE_LINE_SIZE) + L1_CACHE_BYTES) #define IS_TSO_HEADER(txq, addr) \ ((addr >= txq->tso_hdrs_phys) && \ @@ -2764,9 +2763,6 @@ static int mvneta_rxq_init(struct mvneta_port *pp, if (rxq->descs == NULL) return -ENOMEM; - BUG_ON(rxq->descs != - PTR_ALIGN(rxq->descs, MVNETA_CPU_D_CACHE_LINE_SIZE)); - rxq->last_desc = rxq->size - 1; /* Set Rx descriptors queue starting address */ @@ -2837,10 +2833,6 @@ static int mvneta_txq_init(struct mvneta_port *pp, if (txq->descs == NULL) return -ENOMEM; - /* Make sure descriptor address is cache line size aligned */ - BUG_ON(txq->descs != - PTR_ALIGN(txq->descs, MVNETA_CPU_D_CACHE_LINE_SIZE)); - txq->last_desc = txq->size - 1; /* Set maximum bandwidth for enabled TXQs */ -- cgit From 32867fcc0ef9e56939d5200ad983801bbfd581ad Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 31 Mar 2016 12:05:17 -0300 Subject: fec: Do not access unexisting register in Coldfire Commit 55cd48c821de ("net: fec: stop the "rcv is not +last, " error messages") introduces a write to a register that does not exist in Coldfire. Move the FEC_FTRL register access inside the FEC_QUIRK_HAS_RACC 'if' block, so that we guarantee it will not be used on Coldfire CPUs. Reported-by: Greg Ungerer Signed-off-by: Fabio Estevam Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 37c081583084..08243c2ff4b4 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -943,8 +943,8 @@ fec_restart(struct net_device *ndev) else val &= ~FEC_RACC_OPTIONS; writel(val, fep->hwp + FEC_RACC); + writel(PKT_MAXBUF_SIZE, fep->hwp + FEC_FTRL); } - writel(PKT_MAXBUF_SIZE, fep->hwp + FEC_FTRL); #endif /* -- cgit From 79f4223257bfef52b0a26d0d7ad4019e764be6ce Mon Sep 17 00:00:00 2001 From: Daniele Palmas Date: Thu, 31 Mar 2016 15:16:47 +0200 Subject: net: usb: cdc_ncm: adding Telit LE910 V2 mobile broadband card MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Telit LE910 V2 is a mobile broadband card with no ARP capabilities: the patch makes this device to use wwan_noarp_info struct Signed-off-by: Daniele Palmas Reviewed-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/cdc_ncm.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 86ba30ba35e8..2fb31edab125 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -1626,6 +1626,13 @@ static const struct usb_device_id cdc_devs[] = { .driver_info = (unsigned long) &wwan_info, }, + /* Telit LE910 V2 */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1bc7, 0x0036, + USB_CLASS_COMM, + USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&wwan_noarp_info, + }, + /* DW5812 LTE Verizon Mobile Broadband Card * Unlike DW5550 this device requires FLAG_NOARP */ -- cgit From 7779c5e23c5132c22a219f1f5554ef81dd15ee91 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 25 Feb 2016 16:15:05 -0500 Subject: drm/dp: move hw_mutex up the call stack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1) don't let other threads trying to bang on aux channel interrupt the defer timeout/logic 2) don't let other threads interrupt the i2c over aux logic Technically, according to people who actually have the DP spec, this should not be required. In practice, it makes some troublesome Dell monitor (and perhaps others) work, so probably a case of "It's compliant if it works with windows" on the hw vendor's part.. v2: rebased to come before DPCD/AUX logging patch for easier backport to stable branches. Reported-by: Dave Wysochanski Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1274157 Cc: stable@vger.kernel.org Signed-off-by: Rob Clark Reviewed-by: Ville Syrjälä Reviewed-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_dp_helper.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 7d58f594cffe..df64ed1c0139 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -179,7 +179,7 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request, { struct drm_dp_aux_msg msg; unsigned int retry; - int err; + int err = 0; memset(&msg, 0, sizeof(msg)); msg.address = offset; @@ -187,6 +187,8 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request, msg.buffer = buffer; msg.size = size; + mutex_lock(&aux->hw_mutex); + /* * The specification doesn't give any recommendation on how often to * retry native transactions. We used to retry 7 times like for @@ -195,25 +197,24 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request, */ for (retry = 0; retry < 32; retry++) { - mutex_lock(&aux->hw_mutex); err = aux->transfer(aux, &msg); - mutex_unlock(&aux->hw_mutex); if (err < 0) { if (err == -EBUSY) continue; - return err; + goto unlock; } switch (msg.reply & DP_AUX_NATIVE_REPLY_MASK) { case DP_AUX_NATIVE_REPLY_ACK: if (err < size) - return -EPROTO; - return err; + err = -EPROTO; + goto unlock; case DP_AUX_NATIVE_REPLY_NACK: - return -EIO; + err = -EIO; + goto unlock; case DP_AUX_NATIVE_REPLY_DEFER: usleep_range(AUX_RETRY_INTERVAL, AUX_RETRY_INTERVAL + 100); @@ -222,7 +223,11 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request, } DRM_DEBUG_KMS("too many retries, giving up\n"); - return -EIO; + err = -EIO; + +unlock: + mutex_unlock(&aux->hw_mutex); + return err; } /** @@ -544,9 +549,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) int max_retries = max(7, drm_dp_i2c_retry_count(msg, dp_aux_i2c_speed_khz)); for (retry = 0, defer_i2c = 0; retry < (max_retries + defer_i2c); retry++) { - mutex_lock(&aux->hw_mutex); ret = aux->transfer(aux, msg); - mutex_unlock(&aux->hw_mutex); if (ret < 0) { if (ret == -EBUSY) continue; @@ -685,6 +688,8 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, memset(&msg, 0, sizeof(msg)); + mutex_lock(&aux->hw_mutex); + for (i = 0; i < num; i++) { msg.address = msgs[i].addr; drm_dp_i2c_msg_set_request(&msg, &msgs[i]); @@ -739,6 +744,8 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, msg.size = 0; (void)drm_dp_i2c_do_msg(aux, &msg); + mutex_unlock(&aux->hw_mutex); + return err; } -- cgit From 72b9ff0612ad8fc969b910cd00ac16b57a1a9ba4 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 30 Mar 2016 11:40:43 +0200 Subject: drm/udl: Use unlocked gem unreferencing For drm_gem_object_unreference callers are required to hold dev->struct_mutex, which these paths don't. Enforcing this requirement has become a bit more strict with commit ef4c6270bf2867e2f8032e9614d1a8cfc6c71663 Author: Daniel Vetter Date: Thu Oct 15 09:36:25 2015 +0200 drm/gem: Check locking in drm_gem_object_unreference Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/udl/udl_fb.c | 2 +- drivers/gpu/drm/udl/udl_gem.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index 33239a2b264a..fd1eb9d03f0b 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -536,7 +536,7 @@ static int udlfb_create(struct drm_fb_helper *helper, out_destroy_fbi: drm_fb_helper_release_fbi(helper); out_gfree: - drm_gem_object_unreference(&ufbdev->ufb.obj->base); + drm_gem_object_unreference_unlocked(&ufbdev->ufb.obj->base); out: return ret; } diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c index 2a0a784ab6ee..d7528e0d8442 100644 --- a/drivers/gpu/drm/udl/udl_gem.c +++ b/drivers/gpu/drm/udl/udl_gem.c @@ -52,7 +52,7 @@ udl_gem_create(struct drm_file *file, return ret; } - drm_gem_object_unreference(&obj->base); + drm_gem_object_unreference_unlocked(&obj->base); *handle_p = handle; return 0; } -- cgit From 5a5abb1fa3b05dd6aa821525832644c1e7d2905f Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Thu, 31 Mar 2016 02:13:18 +0200 Subject: tun, bpf: fix suspicious RCU usage in tun_{attach, detach}_filter Sasha Levin reported a suspicious rcu_dereference_protected() warning found while fuzzing with trinity that is similar to this one: [ 52.765684] net/core/filter.c:2262 suspicious rcu_dereference_protected() usage! [ 52.765688] other info that might help us debug this: [ 52.765695] rcu_scheduler_active = 1, debug_locks = 1 [ 52.765701] 1 lock held by a.out/1525: [ 52.765704] #0: (rtnl_mutex){+.+.+.}, at: [] rtnl_lock+0x17/0x20 [ 52.765721] stack backtrace: [ 52.765728] CPU: 1 PID: 1525 Comm: a.out Not tainted 4.5.0+ #264 [...] [ 52.765768] Call Trace: [ 52.765775] [] dump_stack+0x85/0xc8 [ 52.765784] [] lockdep_rcu_suspicious+0xd5/0x110 [ 52.765792] [] sk_detach_filter+0x82/0x90 [ 52.765801] [] tun_detach_filter+0x35/0x90 [tun] [ 52.765810] [] __tun_chr_ioctl+0x354/0x1130 [tun] [ 52.765818] [] ? selinux_file_ioctl+0x130/0x210 [ 52.765827] [] tun_chr_ioctl+0x13/0x20 [tun] [ 52.765834] [] do_vfs_ioctl+0x96/0x690 [ 52.765843] [] ? security_file_ioctl+0x43/0x60 [ 52.765850] [] SyS_ioctl+0x79/0x90 [ 52.765858] [] do_syscall_64+0x62/0x140 [ 52.765866] [] entry_SYSCALL64_slow_path+0x25/0x25 Same can be triggered with PROVE_RCU (+ PROVE_RCU_REPEATEDLY) enabled from tun_attach_filter() when user space calls ioctl(tun_fd, TUN{ATTACH, DETACH}FILTER, ...) for adding/removing a BPF filter on tap devices. Since the fix in f91ff5b9ff52 ("net: sk_{detach|attach}_filter() rcu fixes") sk_attach_filter()/sk_detach_filter() now dereferences the filter with rcu_dereference_protected(), checking whether socket lock is held in control path. Since its introduction in 994051625981 ("tun: socket filter support"), tap filters are managed under RTNL lock from __tun_chr_ioctl(). Thus the sock_owned_by_user(sk) doesn't apply in this specific case and therefore triggers the false positive. Extend the BPF API with __sk_attach_filter()/__sk_detach_filter() pair that is used by tap filters and pass in lockdep_rtnl_is_held() for the rcu_dereference_protected() checks instead. Reported-by: Sasha Levin Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller --- drivers/net/tun.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tun.c b/drivers/net/tun.c index afdf950617c3..510e90a6bb26 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -622,7 +622,8 @@ static int tun_attach(struct tun_struct *tun, struct file *file, bool skip_filte /* Re-attach the filter to persist device */ if (!skip_filter && (tun->filter_attached == true)) { - err = sk_attach_filter(&tun->fprog, tfile->socket.sk); + err = __sk_attach_filter(&tun->fprog, tfile->socket.sk, + lockdep_rtnl_is_held()); if (!err) goto out; } @@ -1822,7 +1823,7 @@ static void tun_detach_filter(struct tun_struct *tun, int n) for (i = 0; i < n; i++) { tfile = rtnl_dereference(tun->tfiles[i]); - sk_detach_filter(tfile->socket.sk); + __sk_detach_filter(tfile->socket.sk, lockdep_rtnl_is_held()); } tun->filter_attached = false; @@ -1835,7 +1836,8 @@ static int tun_attach_filter(struct tun_struct *tun) for (i = 0; i < tun->numqueues; i++) { tfile = rtnl_dereference(tun->tfiles[i]); - ret = sk_attach_filter(&tun->fprog, tfile->socket.sk); + ret = __sk_attach_filter(&tun->fprog, tfile->socket.sk, + lockdep_rtnl_is_held()); if (ret) { tun_detach_filter(tun, i); return ret; -- cgit From d82b0c21d44d1cc61a23db56c2b2cf52ea9f3220 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Thu, 31 Mar 2016 17:01:23 +0800 Subject: net: mvpp2: fix maybe-uninitialized warning This is to fix the following maybe-uninitialized warning: drivers/net/ethernet/marvell/mvpp2.c:6007:18: warning: 'err' may be used uninitialized in this function [-Wmaybe-uninitialized] Signed-off-by: Jisheng Zhang Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c index 05f358b81791..2750cb978f42 100644 --- a/drivers/net/ethernet/marvell/mvpp2.c +++ b/drivers/net/ethernet/marvell/mvpp2.c @@ -6047,8 +6047,10 @@ static int mvpp2_port_init(struct mvpp2_port *port) /* Map physical Rx queue to port's logical Rx queue */ rxq = devm_kzalloc(dev, sizeof(*rxq), GFP_KERNEL); - if (!rxq) + if (!rxq) { + err = -ENOMEM; goto err_free_percpu; + } /* Map this Rx queue to a physical queue */ rxq->id = port->first_rxq + queue; rxq->port = port->id; -- cgit From 4a0a12d27ca5e892579f3c61c18c8dcfebf425d4 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Fri, 1 Apr 2016 17:11:05 +0800 Subject: net: mvpp2: use cache_line_size() to get cacheline size L1_CACHE_BYTES may not be the real cacheline size, use cache_line_size to determine the cacheline size in runtime. Signed-off-by: Jisheng Zhang Suggested-by: Marcin Wojtas Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c index 2750cb978f42..868a957f24bb 100644 --- a/drivers/net/ethernet/marvell/mvpp2.c +++ b/drivers/net/ethernet/marvell/mvpp2.c @@ -376,7 +376,7 @@ #define MVPP2_RX_PKT_SIZE(mtu) \ ALIGN((mtu) + MVPP2_MH_SIZE + MVPP2_VLAN_TAG_LEN + \ - ETH_HLEN + ETH_FCS_LEN, L1_CACHE_BYTES) + ETH_HLEN + ETH_FCS_LEN, cache_line_size()) #define MVPP2_RX_BUF_SIZE(pkt_size) ((pkt_size) + NET_SKB_PAD) #define MVPP2_RX_TOTAL_SIZE(buf_size) ((buf_size) + MVPP2_SKB_SHINFO_SIZE) -- cgit From c66e98c9532bf7b58fe78cc59fb37d3ff651756d Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Fri, 1 Apr 2016 17:12:49 +0800 Subject: net: mvneta: use cache_line_size() to get cacheline size L1_CACHE_BYTES may not be the real cacheline size, use cache_line_size to determine the cacheline size in runtime. Signed-off-by: Jisheng Zhang Suggested-by: Marcin Wojtas Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvneta.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 58808718d114..b1db000f1927 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -299,7 +299,7 @@ #define MVNETA_RX_PKT_SIZE(mtu) \ ALIGN((mtu) + MVNETA_MH_SIZE + MVNETA_VLAN_TAG_LEN + \ ETH_HLEN + ETH_FCS_LEN, \ - L1_CACHE_BYTES) + cache_line_size()) #define IS_TSO_HEADER(txq, addr) \ ((addr >= txq->tso_hdrs_phys) && \ -- cgit From a00e3ab64be2e482bd25fe30bdc9bfa6e2b0cf1c Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Fri, 1 Apr 2016 09:07:14 +0200 Subject: stmmac: fix TX normal DESC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixs a regression raised when test on chips that use the normal descriptor layout. In fact, no len bits were set for the TDES1 and no OWN bit inside the TDES0. Signed-off-by: Giuseppe CAVALLARO Tested-by: Andreas Färber Cc: Fabrice Gasnier Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/norm_desc.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c index e13228f115f0..011386f6f24d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c +++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c @@ -199,11 +199,6 @@ static void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len, { unsigned int tdes1 = p->des1; - if (mode == STMMAC_CHAIN_MODE) - norm_set_tx_desc_len_on_chain(p, len); - else - norm_set_tx_desc_len_on_ring(p, len); - if (is_fs) tdes1 |= TDES1_FIRST_SEGMENT; else @@ -217,10 +212,15 @@ static void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len, if (ls) tdes1 |= TDES1_LAST_SEGMENT; - if (tx_own) - tdes1 |= TDES0_OWN; - p->des1 = tdes1; + + if (mode == STMMAC_CHAIN_MODE) + norm_set_tx_desc_len_on_chain(p, len); + else + norm_set_tx_desc_len_on_ring(p, len); + + if (tx_own) + p->des0 |= TDES0_OWN; } static void ndesc_set_tx_ic(struct dma_desc *p) -- cgit From d7e944c8ddc0983640a9a32868fb217485d12ca2 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Fri, 1 Apr 2016 09:07:15 +0200 Subject: Revert "stmmac: Fix 'eth0: No PHY found' regression" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 88f8b1bb41c6208f81b6a480244533ded7b59493. due to problems on GeekBox and Banana Pi M1 board when connected to a real transceiver instead of a switch via fixed-link. Signed-off-by: Giuseppe Cavallaro Cc: Gabriel Fernandez Cc: Andreas Färber Cc: Frank Schäfer Cc: Dinh Nguyen Cc: David S. Miller Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 11 ++++++++++- drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 9 +-------- 2 files changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index ea76129dafc2..af09ced53bd8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -199,12 +199,21 @@ int stmmac_mdio_register(struct net_device *ndev) struct stmmac_priv *priv = netdev_priv(ndev); struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data; int addr, found; - struct device_node *mdio_node = priv->plat->mdio_node; + struct device_node *mdio_node = NULL; + struct device_node *child_node = NULL; if (!mdio_bus_data) return 0; if (IS_ENABLED(CONFIG_OF)) { + for_each_child_of_node(priv->device->of_node, child_node) { + if (of_device_is_compatible(child_node, + "snps,dwmac-mdio")) { + mdio_node = child_node; + break; + } + } + if (mdio_node) { netdev_dbg(ndev, "FOUND MDIO subnode\n"); } else { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index dcbd2a1601e8..9cf181f839fd 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -146,7 +146,6 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) struct device_node *np = pdev->dev.of_node; struct plat_stmmacenet_data *plat; struct stmmac_dma_cfg *dma_cfg; - struct device_node *child_node = NULL; plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL); if (!plat) @@ -177,19 +176,13 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) plat->phy_node = of_node_get(np); } - for_each_child_of_node(np, child_node) - if (of_device_is_compatible(child_node, "snps,dwmac-mdio")) { - plat->mdio_node = child_node; - break; - } - /* "snps,phy-addr" is not a standard property. Mark it as deprecated * and warn of its use. Remove this when phy node support is added. */ if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0) dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n"); - if ((plat->phy_node && !of_phy_is_fixed_link(np)) || !plat->mdio_node) + if ((plat->phy_node && !of_phy_is_fixed_link(np)) || plat->phy_bus_name) plat->mdio_bus_data = NULL; else plat->mdio_bus_data = -- cgit From a7657f128c279ae5796ab2ca7d04a7819f4259f0 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Fri, 1 Apr 2016 09:07:16 +0200 Subject: stmmac: fix MDIO settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Initially the phy_bus_name was added to manipulate the driver name but it was recently just used to manage the fixed-link and then to take some decision at run-time. So the patch uses the is_pseudo_fixed_link and removes the phy_bus_name variable not necessary anymore. The driver can manage the mdio registration by using phy-handle, dwmac-mdio and own parameter e.g. snps,phy-addr. This patch takes care about all these possible configurations and fixes the mdio registration in case of there is a real transceiver or a switch (that needs to be managed by using fixed-link). Signed-off-by: Giuseppe Cavallaro Reviewed-by: Andreas Färber Tested-by: Frank Schäfer Cc: Gabriel Fernandez Cc: Dinh Nguyen Cc: David S. Miller Cc: Phil Reid Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 16 ++--- drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 19 +---- .../net/ethernet/stmicro/stmmac/stmmac_platform.c | 84 +++++++++++++++++----- 3 files changed, 72 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 4c5ce9848ca9..78464fa7fe1f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -278,7 +278,6 @@ static void stmmac_eee_ctrl_timer(unsigned long arg) */ bool stmmac_eee_init(struct stmmac_priv *priv) { - char *phy_bus_name = priv->plat->phy_bus_name; unsigned long flags; bool ret = false; @@ -290,7 +289,7 @@ bool stmmac_eee_init(struct stmmac_priv *priv) goto out; /* Never init EEE in case of a switch is attached */ - if (phy_bus_name && (!strcmp(phy_bus_name, "fixed"))) + if (priv->phydev->is_pseudo_fixed_link) goto out; /* MAC core supports the EEE feature. */ @@ -827,12 +826,8 @@ static int stmmac_init_phy(struct net_device *dev) phydev = of_phy_connect(dev, priv->plat->phy_node, &stmmac_adjust_link, 0, interface); } else { - if (priv->plat->phy_bus_name) - snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x", - priv->plat->phy_bus_name, priv->plat->bus_id); - else - snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x", - priv->plat->bus_id); + snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x", + priv->plat->bus_id); snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id, priv->plat->phy_addr); @@ -871,9 +866,8 @@ static int stmmac_init_phy(struct net_device *dev) } /* If attached to a switch, there is no reason to poll phy handler */ - if (priv->plat->phy_bus_name) - if (!strcmp(priv->plat->phy_bus_name, "fixed")) - phydev->irq = PHY_IGNORE_INTERRUPT; + if (phydev->is_pseudo_fixed_link) + phydev->irq = PHY_IGNORE_INTERRUPT; pr_debug("stmmac_init_phy: %s: attached to PHY (UID 0x%x)" " Link = %d\n", dev->name, phydev->phy_id, phydev->link); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index af09ced53bd8..06704ca6f9ca 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -198,29 +198,12 @@ int stmmac_mdio_register(struct net_device *ndev) struct mii_bus *new_bus; struct stmmac_priv *priv = netdev_priv(ndev); struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data; + struct device_node *mdio_node = priv->plat->mdio_node; int addr, found; - struct device_node *mdio_node = NULL; - struct device_node *child_node = NULL; if (!mdio_bus_data) return 0; - if (IS_ENABLED(CONFIG_OF)) { - for_each_child_of_node(priv->device->of_node, child_node) { - if (of_device_is_compatible(child_node, - "snps,dwmac-mdio")) { - mdio_node = child_node; - break; - } - } - - if (mdio_node) { - netdev_dbg(ndev, "FOUND MDIO subnode\n"); - } else { - netdev_warn(ndev, "No MDIO subnode found\n"); - } - } - new_bus = mdiobus_alloc(); if (new_bus == NULL) return -ENOMEM; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index 9cf181f839fd..cf37ea558ecc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -131,6 +131,69 @@ static struct stmmac_axi *stmmac_axi_setup(struct platform_device *pdev) return axi; } +/** + * stmmac_dt_phy - parse device-tree driver parameters to allocate PHY resources + * @plat: driver data platform structure + * @np: device tree node + * @dev: device pointer + * Description: + * The mdio bus will be allocated in case of a phy transceiver is on board; + * it will be NULL if the fixed-link is configured. + * If there is the "snps,dwmac-mdio" sub-node the mdio will be allocated + * in any case (for DSA, mdio must be registered even if fixed-link). + * The table below sums the supported configurations: + * ------------------------------- + * snps,phy-addr | Y + * ------------------------------- + * phy-handle | Y + * ------------------------------- + * fixed-link | N + * ------------------------------- + * snps,dwmac-mdio | + * even if | Y + * fixed-link | + * ------------------------------- + * + * It returns 0 in case of success otherwise -ENODEV. + */ +static int stmmac_dt_phy(struct plat_stmmacenet_data *plat, + struct device_node *np, struct device *dev) +{ + bool mdio = true; + + /* If phy-handle property is passed from DT, use it as the PHY */ + plat->phy_node = of_parse_phandle(np, "phy-handle", 0); + if (plat->phy_node) + dev_dbg(dev, "Found phy-handle subnode\n"); + + /* If phy-handle is not specified, check if we have a fixed-phy */ + if (!plat->phy_node && of_phy_is_fixed_link(np)) { + if ((of_phy_register_fixed_link(np) < 0)) + return -ENODEV; + + dev_dbg(dev, "Found fixed-link subnode\n"); + plat->phy_node = of_node_get(np); + mdio = false; + } + + /* If snps,dwmac-mdio is passed from DT, always register the MDIO */ + for_each_child_of_node(np, plat->mdio_node) { + if (of_device_is_compatible(plat->mdio_node, "snps,dwmac-mdio")) + break; + } + + if (plat->mdio_node) { + dev_dbg(dev, "Found MDIO subnode\n"); + mdio = true; + } + + if (mdio) + plat->mdio_bus_data = + devm_kzalloc(dev, sizeof(struct stmmac_mdio_bus_data), + GFP_KERNEL); + return 0; +} + /** * stmmac_probe_config_dt - parse device-tree driver parameters * @pdev: platform_device structure @@ -165,30 +228,15 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) /* Default to phy auto-detection */ plat->phy_addr = -1; - /* If we find a phy-handle property, use it as the PHY */ - plat->phy_node = of_parse_phandle(np, "phy-handle", 0); - - /* If phy-handle is not specified, check if we have a fixed-phy */ - if (!plat->phy_node && of_phy_is_fixed_link(np)) { - if ((of_phy_register_fixed_link(np) < 0)) - return ERR_PTR(-ENODEV); - - plat->phy_node = of_node_get(np); - } - /* "snps,phy-addr" is not a standard property. Mark it as deprecated * and warn of its use. Remove this when phy node support is added. */ if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0) dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n"); - if ((plat->phy_node && !of_phy_is_fixed_link(np)) || plat->phy_bus_name) - plat->mdio_bus_data = NULL; - else - plat->mdio_bus_data = - devm_kzalloc(&pdev->dev, - sizeof(struct stmmac_mdio_bus_data), - GFP_KERNEL); + /* To Configure PHY by using all device-tree supported properties */ + if (stmmac_dt_phy(plat, np, &pdev->dev)) + return ERR_PTR(-ENODEV); of_property_read_u32(np, "tx-fifo-depth", &plat->tx_fifo_size); -- cgit From db5dd0db2d8352bb7fd5e9d16e17b79d66c7e4e3 Mon Sep 17 00:00:00 2001 From: Marcin Wojtas Date: Fri, 1 Apr 2016 15:21:18 +0200 Subject: net: mvneta: fix changing MTU when using per-cpu processing After enabling per-cpu processing it appeared that under heavy load changing MTU can result in blocking all port's interrupts and transmitting data is not possible after the change. This commit fixes above issue by disabling percpu interrupts for the time, when TXQs and RXQs are reconfigured. Signed-off-by: Marcin Wojtas Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvneta.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index b1db000f1927..7fc490225da5 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -3042,6 +3042,20 @@ static int mvneta_check_mtu_valid(struct net_device *dev, int mtu) return mtu; } +static void mvneta_percpu_enable(void *arg) +{ + struct mvneta_port *pp = arg; + + enable_percpu_irq(pp->dev->irq, IRQ_TYPE_NONE); +} + +static void mvneta_percpu_disable(void *arg) +{ + struct mvneta_port *pp = arg; + + disable_percpu_irq(pp->dev->irq); +} + /* Change the device mtu */ static int mvneta_change_mtu(struct net_device *dev, int mtu) { @@ -3066,6 +3080,7 @@ static int mvneta_change_mtu(struct net_device *dev, int mtu) * reallocation of the queues */ mvneta_stop_dev(pp); + on_each_cpu(mvneta_percpu_disable, pp, true); mvneta_cleanup_txqs(pp); mvneta_cleanup_rxqs(pp); @@ -3089,6 +3104,7 @@ static int mvneta_change_mtu(struct net_device *dev, int mtu) return ret; } + on_each_cpu(mvneta_percpu_enable, pp, true); mvneta_start_dev(pp); mvneta_port_up(pp); @@ -3242,20 +3258,6 @@ static void mvneta_mdio_remove(struct mvneta_port *pp) pp->phy_dev = NULL; } -static void mvneta_percpu_enable(void *arg) -{ - struct mvneta_port *pp = arg; - - enable_percpu_irq(pp->dev->irq, IRQ_TYPE_NONE); -} - -static void mvneta_percpu_disable(void *arg) -{ - struct mvneta_port *pp = arg; - - disable_percpu_irq(pp->dev->irq); -} - /* Electing a CPU must be done in an atomic way: it should be done * after or before the removal/insertion of a CPU and this function is * not reentrant. -- cgit From cb107161df3c52e58033554dcb40065964350f67 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 2 Apr 2016 18:35:05 -0500 Subject: Convert straggling drivers to new six-argument get_user_pages() Commit d4edcf0d5695 ("mm/gup: Switch all callers of get_user_pages() to not pass tsk/mm") switched get_user_pages() callers to the simpler model where they no longer pass in the thread and mm pointer. But since then we've merged changes to a few drivers that re-introduce use of the old interface. Let's fix them up. They continued to work fine (thanks to the truly disgusting macros introduced in commit cde70140fed8: "mm/gup: Overload get_user_pages() functions"), but cause unnecessary build noise. Signed-off-by: Linus Torvalds --- drivers/platform/goldfish/goldfish_pipe.c | 3 +-- drivers/rapidio/devices/rio_mport_cdev.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c index 9973cebb4d6f..07462d79d040 100644 --- a/drivers/platform/goldfish/goldfish_pipe.c +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -309,8 +309,7 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, * much memory to the process. */ down_read(¤t->mm->mmap_sem); - ret = get_user_pages(current, current->mm, address, 1, - !is_write, 0, &page, NULL); + ret = get_user_pages(address, 1, !is_write, 0, &page, NULL); up_read(¤t->mm->mmap_sem); if (ret < 0) break; diff --git a/drivers/rapidio/devices/rio_mport_cdev.c b/drivers/rapidio/devices/rio_mport_cdev.c index 9607bc826460..5d4d91846357 100644 --- a/drivers/rapidio/devices/rio_mport_cdev.c +++ b/drivers/rapidio/devices/rio_mport_cdev.c @@ -886,7 +886,7 @@ rio_dma_transfer(struct file *filp, uint32_t transfer_mode, } down_read(¤t->mm->mmap_sem); - pinned = get_user_pages(current, current->mm, + pinned = get_user_pages( (unsigned long)xfer->loc_addr & PAGE_MASK, nr_pages, dir == DMA_FROM_DEVICE, 0, page_list, NULL); -- cgit From 17084b7e07909d3a8d51b66b7dfb50a2083a2685 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 3 Apr 2016 07:03:49 -0500 Subject: v4l2-mc: avoid warning about unused variable Commit 840f5b0572ea ("media: au0828 disable tuner to demod link in au0828_media_device_register()") removed all uses of the 'dtv_demod', but left the variable itself around. Remove it. Signed-off-by: Linus Torvalds --- drivers/media/v4l2-core/v4l2-mc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c index 2a7b79bc90fd..2228cd3a846e 100644 --- a/drivers/media/v4l2-core/v4l2-mc.c +++ b/drivers/media/v4l2-core/v4l2-mc.c @@ -34,7 +34,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) { struct media_entity *entity; struct media_entity *if_vid = NULL, *if_aud = NULL; - struct media_entity *tuner = NULL, *decoder = NULL, *dtv_demod = NULL; + struct media_entity *tuner = NULL, *decoder = NULL; struct media_entity *io_v4l = NULL, *io_vbi = NULL, *io_swradio = NULL; bool is_webcam = false; u32 flags; -- cgit From ea6db90e750328068837bed34cb1302b7a177339 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 10 Mar 2016 09:48:52 -0500 Subject: USB: serial: ftdi_sio: Add support for ICP DAS I-756xU devices A Fedora user reports that the ftdi_sio driver works properly for the ICP DAS I-7561U device. Further, the user manual for these devices instructs users to load the driver and add the ids using the sysfs interface. Add support for these in the driver directly so that the devices work out of the box instead of needing manual configuration. Reported-by: CC: stable Signed-off-by: Josh Boyer Signed-off-by: Johan Hovold --- drivers/usb/serial/ftdi_sio.c | 4 ++++ drivers/usb/serial/ftdi_sio_ids.h | 8 ++++++++ 2 files changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 427ae43ee898..3a814e802dee 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1004,6 +1004,10 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_DISPLAY_PID) }, { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_LITE_PID) }, { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ANALOG_PID) }, + /* ICP DAS I-756xU devices */ + { USB_DEVICE(ICPDAS_VID, ICPDAS_I7560U_PID) }, + { USB_DEVICE(ICPDAS_VID, ICPDAS_I7561U_PID) }, + { USB_DEVICE(ICPDAS_VID, ICPDAS_I7563U_PID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index a84df2513994..c5d6c1e73e8e 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -871,6 +871,14 @@ #define NOVITUS_VID 0x1a28 #define NOVITUS_BONO_E_PID 0x6010 +/* + * ICPDAS I-756*U devices + */ +#define ICPDAS_VID 0x1b5c +#define ICPDAS_I7560U_PID 0x0103 +#define ICPDAS_I7561U_PID 0x0104 +#define ICPDAS_I7563U_PID 0x0105 + /* * RT Systems programming cables for various ham radios */ -- cgit From cddc9434e3dcc37a85c4412fb8e277d3a582e456 Mon Sep 17 00:00:00 2001 From: Martyn Welch Date: Tue, 29 Mar 2016 17:47:29 +0100 Subject: USB: serial: cp210x: Adding GE Healthcare Device ID The CP2105 is used in the GE Healthcare Remote Alarm Box, with the Manufacturer ID of 0x1901 and Product ID of 0x0194. Signed-off-by: Martyn Welch Cc: stable Signed-off-by: Johan Hovold --- drivers/usb/serial/cp210x.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index fbfe761c7fba..dd47823bb014 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -165,6 +165,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x18EF, 0xE025) }, /* ELV Marble Sound Board 1 */ { USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */ { USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */ + { USB_DEVICE(0x1901, 0x0194) }, /* GE Healthcare Remote Alarm Box */ { USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */ { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */ { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */ -- cgit From d48d5691ebf88a15d95ba96486917ffc79256536 Mon Sep 17 00:00:00 2001 From: Bjørn Mork Date: Thu, 7 Apr 2016 12:09:17 +0200 Subject: USB: option: add "D-Link DWM-221 B1" device id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thomas reports: "Windows: 00 diagnostics 01 modem 02 at-port 03 nmea 04 nic Linux: T: Bus=02 Lev=01 Prnt=01 Port=03 Cnt=01 Dev#= 4 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=2001 ProdID=7e19 Rev=02.32 S: Manufacturer=Mobile Connect S: Product=Mobile Connect S: SerialNumber=0123456789ABCDEF C: #Ifs= 6 Cfg#= 1 Atr=a0 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option I: If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option I: If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option I: If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option I: If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan I: If#= 5 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage" Reported-by: Thomas Schäfer Cc: Signed-off-by: Bjørn Mork Signed-off-by: Johan Hovold --- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 348e19834b83..c6f497f16526 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1818,6 +1818,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x00, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x02, 0x01) }, { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) }, + { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e19, 0xff), /* D-Link DWM-221 B1 */ + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */ { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */ { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x4000, 0xff) }, /* OLICARD300 - MT6225 */ -- cgit