mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-13 09:28:44 -04:00
Backmerge tag 'v4.7-rc2' into drm-next
Daniel has a pull request that relies on stuff in fixes that are in rc2.
This commit is contained in:
@@ -331,15 +331,6 @@ static int acpi_processor_get_info(struct acpi_device *device)
|
||||
pr->throttling.duty_width = acpi_gbl_FADT.duty_width;
|
||||
|
||||
pr->pblk = object.processor.pblk_address;
|
||||
|
||||
/*
|
||||
* We don't care about error returns - we just try to mark
|
||||
* these reserved so that nobody else is confused into thinking
|
||||
* that this region might be unused..
|
||||
*
|
||||
* (In particular, allocating the IO range for Cardbus)
|
||||
*/
|
||||
request_region(pr->throttling.address, 6, "ACPI CPU throttle");
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -754,7 +754,8 @@ static int acpi_video_bqc_quirk(struct acpi_video_device *device,
|
||||
}
|
||||
|
||||
int acpi_video_get_levels(struct acpi_device *device,
|
||||
struct acpi_video_device_brightness **dev_br)
|
||||
struct acpi_video_device_brightness **dev_br,
|
||||
int *pmax_level)
|
||||
{
|
||||
union acpi_object *obj = NULL;
|
||||
int i, max_level = 0, count = 0, level_ac_battery = 0;
|
||||
@@ -841,6 +842,8 @@ int acpi_video_get_levels(struct acpi_device *device,
|
||||
|
||||
br->count = count;
|
||||
*dev_br = br;
|
||||
if (pmax_level)
|
||||
*pmax_level = max_level;
|
||||
|
||||
out:
|
||||
kfree(obj);
|
||||
@@ -869,7 +872,7 @@ acpi_video_init_brightness(struct acpi_video_device *device)
|
||||
struct acpi_video_device_brightness *br = NULL;
|
||||
int result = -EINVAL;
|
||||
|
||||
result = acpi_video_get_levels(device->dev, &br);
|
||||
result = acpi_video_get_levels(device->dev, &br, &max_level);
|
||||
if (result)
|
||||
return result;
|
||||
device->brightness = br;
|
||||
@@ -1737,7 +1740,7 @@ static void acpi_video_run_bcl_for_osi(struct acpi_video_bus *video)
|
||||
|
||||
mutex_lock(&video->device_list_lock);
|
||||
list_for_each_entry(dev, &video->video_device_list, entry) {
|
||||
if (!acpi_video_device_lcd_query_levels(dev, &levels))
|
||||
if (!acpi_video_device_lcd_query_levels(dev->dev->handle, &levels))
|
||||
kfree(levels);
|
||||
}
|
||||
mutex_unlock(&video->device_list_lock);
|
||||
|
||||
@@ -83,27 +83,22 @@ acpi_hw_write_multiple(u32 value,
|
||||
static u8
|
||||
acpi_hw_get_access_bit_width(struct acpi_generic_address *reg, u8 max_bit_width)
|
||||
{
|
||||
u64 address;
|
||||
|
||||
if (!reg->access_width) {
|
||||
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
|
||||
max_bit_width = 32;
|
||||
}
|
||||
|
||||
/*
|
||||
* Detect old register descriptors where only the bit_width field
|
||||
* makes senses. The target address is copied to handle possible
|
||||
* alignment issues.
|
||||
* makes senses.
|
||||
*/
|
||||
ACPI_MOVE_64_TO_64(&address, ®->address);
|
||||
if (!reg->bit_offset && reg->bit_width &&
|
||||
if (reg->bit_width < max_bit_width &&
|
||||
!reg->bit_offset && reg->bit_width &&
|
||||
ACPI_IS_POWER_OF_TWO(reg->bit_width) &&
|
||||
ACPI_IS_ALIGNED(reg->bit_width, 8) &&
|
||||
ACPI_IS_ALIGNED(address, reg->bit_width)) {
|
||||
ACPI_IS_ALIGNED(reg->bit_width, 8)) {
|
||||
return (reg->bit_width);
|
||||
} else {
|
||||
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
|
||||
return (32);
|
||||
} else {
|
||||
return (max_bit_width);
|
||||
}
|
||||
}
|
||||
return (max_bit_width);
|
||||
} else {
|
||||
return (1 << (reg->access_width + 2));
|
||||
}
|
||||
|
||||
@@ -676,6 +676,15 @@ static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr)
|
||||
if (!pr->flags.throttling)
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* We don't care about error returns - we just try to mark
|
||||
* these reserved so that nobody else is confused into thinking
|
||||
* that this region might be unused..
|
||||
*
|
||||
* (In particular, allocating the IO range for Cardbus)
|
||||
*/
|
||||
request_region(pr->throttling.address, 6, "ACPI CPU throttle");
|
||||
|
||||
pr->throttling.state = 0;
|
||||
|
||||
duty_mask = pr->throttling.state_count - 1;
|
||||
|
||||
@@ -181,13 +181,17 @@ static char *res_strings[] = {
|
||||
"reserved 27",
|
||||
"reserved 28",
|
||||
"reserved 29",
|
||||
"reserved 30",
|
||||
"reserved 30", /* FIXME: The strings between 30-40 might be wrong. */
|
||||
"reassembly abort: no buffers",
|
||||
"receive buffer overflow",
|
||||
"change in GFC",
|
||||
"receive buffer full",
|
||||
"low priority discard - no receive descriptor",
|
||||
"low priority discard - missing end of packet",
|
||||
"reserved 37",
|
||||
"reserved 38",
|
||||
"reserved 39",
|
||||
"reseverd 40",
|
||||
"reserved 41",
|
||||
"reserved 42",
|
||||
"reserved 43",
|
||||
|
||||
@@ -1128,7 +1128,7 @@ static int rx_pkt(struct atm_dev *dev)
|
||||
/* make the ptr point to the corresponding buffer desc entry */
|
||||
buf_desc_ptr += desc;
|
||||
if (!desc || (desc > iadev->num_rx_desc) ||
|
||||
((buf_desc_ptr->vc_index & 0xffff) > iadev->num_vc)) {
|
||||
((buf_desc_ptr->vc_index & 0xffff) >= iadev->num_vc)) {
|
||||
free_desc(dev, desc);
|
||||
IF_ERR(printk("IA: bad descriptor desc = %d \n", desc);)
|
||||
return -1;
|
||||
|
||||
@@ -1832,7 +1832,7 @@ EXPORT_SYMBOL(cpufreq_unregister_notifier);
|
||||
unsigned int cpufreq_driver_fast_switch(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq)
|
||||
{
|
||||
clamp_val(target_freq, policy->min, policy->max);
|
||||
target_freq = clamp_val(target_freq, policy->min, policy->max);
|
||||
|
||||
return cpufreq_driver->fast_switch(policy, target_freq);
|
||||
}
|
||||
|
||||
@@ -449,7 +449,7 @@ static void intel_pstate_init_acpi_perf_limits(struct cpufreq_policy *policy)
|
||||
cpu->acpi_perf_data.states[0].core_frequency =
|
||||
policy->cpuinfo.max_freq / 1000;
|
||||
cpu->valid_pss_table = true;
|
||||
pr_info("_PPC limits will be enforced\n");
|
||||
pr_debug("_PPC limits will be enforced\n");
|
||||
|
||||
return;
|
||||
|
||||
|
||||
@@ -122,6 +122,7 @@ static int ccp_aes_xts_crypt(struct ablkcipher_request *req,
|
||||
struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
|
||||
struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req);
|
||||
unsigned int unit;
|
||||
u32 unit_size;
|
||||
int ret;
|
||||
|
||||
if (!ctx->u.aes.key_len)
|
||||
@@ -133,11 +134,17 @@ static int ccp_aes_xts_crypt(struct ablkcipher_request *req,
|
||||
if (!req->info)
|
||||
return -EINVAL;
|
||||
|
||||
for (unit = 0; unit < ARRAY_SIZE(unit_size_map); unit++)
|
||||
if (!(req->nbytes & (unit_size_map[unit].size - 1)))
|
||||
break;
|
||||
unit_size = CCP_XTS_AES_UNIT_SIZE__LAST;
|
||||
if (req->nbytes <= unit_size_map[0].size) {
|
||||
for (unit = 0; unit < ARRAY_SIZE(unit_size_map); unit++) {
|
||||
if (!(req->nbytes & (unit_size_map[unit].size - 1))) {
|
||||
unit_size = unit_size_map[unit].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((unit_size_map[unit].value == CCP_XTS_AES_UNIT_SIZE__LAST) ||
|
||||
if ((unit_size == CCP_XTS_AES_UNIT_SIZE__LAST) ||
|
||||
(ctx->u.aes.key_len != AES_KEYSIZE_128)) {
|
||||
/* Use the fallback to process the request for any
|
||||
* unsupported unit sizes or key sizes
|
||||
@@ -158,7 +165,7 @@ static int ccp_aes_xts_crypt(struct ablkcipher_request *req,
|
||||
rctx->cmd.engine = CCP_ENGINE_XTS_AES_128;
|
||||
rctx->cmd.u.xts.action = (encrypt) ? CCP_AES_ACTION_ENCRYPT
|
||||
: CCP_AES_ACTION_DECRYPT;
|
||||
rctx->cmd.u.xts.unit_size = unit_size_map[unit].value;
|
||||
rctx->cmd.u.xts.unit_size = unit_size;
|
||||
rctx->cmd.u.xts.key = &ctx->u.aes.key_sg;
|
||||
rctx->cmd.u.xts.key_len = ctx->u.aes.key_len;
|
||||
rctx->cmd.u.xts.iv = &rctx->iv_sg;
|
||||
|
||||
@@ -1986,7 +1986,7 @@ static int omap_sham_probe(struct platform_device *pdev)
|
||||
&dd->pdata->algs_info[i].algs_list[j]);
|
||||
err_pm:
|
||||
pm_runtime_disable(dev);
|
||||
if (dd->polling_mode)
|
||||
if (!dd->polling_mode)
|
||||
dma_release_channel(dd->dma_lch);
|
||||
data_err:
|
||||
dev_err(dev, "initialization failed.\n");
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/reservation.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include <uapi/linux/dma-buf.h>
|
||||
|
||||
@@ -90,7 +91,7 @@ static int dma_buf_mmap_internal(struct file *file, struct vm_area_struct *vma)
|
||||
dmabuf = file->private_data;
|
||||
|
||||
/* check for overflowing the buffer's size */
|
||||
if (vma->vm_pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) >
|
||||
if (vma->vm_pgoff + vma_pages(vma) >
|
||||
dmabuf->size >> PAGE_SHIFT)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -723,11 +724,11 @@ int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
|
||||
return -EINVAL;
|
||||
|
||||
/* check for offset overflow */
|
||||
if (pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) < pgoff)
|
||||
if (pgoff + vma_pages(vma) < pgoff)
|
||||
return -EOVERFLOW;
|
||||
|
||||
/* check for overflowing the buffer's size */
|
||||
if (pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) >
|
||||
if (pgoff + vma_pages(vma) >
|
||||
dmabuf->size >> PAGE_SHIFT)
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
@@ -35,6 +35,17 @@
|
||||
#include <linux/reservation.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
/**
|
||||
* DOC: Reservation Object Overview
|
||||
*
|
||||
* The reservation object provides a mechanism to manage shared and
|
||||
* exclusive fences associated with a buffer. A reservation object
|
||||
* can have attached one exclusive fence (normally associated with
|
||||
* write operations) or N shared fences (read operations). The RCU
|
||||
* mechanism is used to protect read access to fences from locked
|
||||
* write-side updates.
|
||||
*/
|
||||
|
||||
DEFINE_WW_CLASS(reservation_ww_class);
|
||||
EXPORT_SYMBOL(reservation_ww_class);
|
||||
|
||||
@@ -43,9 +54,17 @@ EXPORT_SYMBOL(reservation_seqcount_class);
|
||||
|
||||
const char reservation_seqcount_string[] = "reservation_seqcount";
|
||||
EXPORT_SYMBOL(reservation_seqcount_string);
|
||||
/*
|
||||
* Reserve space to add a shared fence to a reservation_object,
|
||||
* must be called with obj->lock held.
|
||||
|
||||
/**
|
||||
* reservation_object_reserve_shared - Reserve space to add a shared
|
||||
* fence to a reservation_object.
|
||||
* @obj: reservation object
|
||||
*
|
||||
* Should be called before reservation_object_add_shared_fence(). Must
|
||||
* be called with obj->lock held.
|
||||
*
|
||||
* RETURNS
|
||||
* Zero for success, or -errno
|
||||
*/
|
||||
int reservation_object_reserve_shared(struct reservation_object *obj)
|
||||
{
|
||||
@@ -180,7 +199,11 @@ reservation_object_add_shared_replace(struct reservation_object *obj,
|
||||
fence_put(old_fence);
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* reservation_object_add_shared_fence - Add a fence to a shared slot
|
||||
* @obj: the reservation object
|
||||
* @fence: the shared fence to add
|
||||
*
|
||||
* Add a fence to a shared slot, obj->lock must be held, and
|
||||
* reservation_object_reserve_shared_fence has been called.
|
||||
*/
|
||||
@@ -200,6 +223,13 @@ void reservation_object_add_shared_fence(struct reservation_object *obj,
|
||||
}
|
||||
EXPORT_SYMBOL(reservation_object_add_shared_fence);
|
||||
|
||||
/**
|
||||
* reservation_object_add_excl_fence - Add an exclusive fence.
|
||||
* @obj: the reservation object
|
||||
* @fence: the shared fence to add
|
||||
*
|
||||
* Add a fence to the exclusive slot. The obj->lock must be held.
|
||||
*/
|
||||
void reservation_object_add_excl_fence(struct reservation_object *obj,
|
||||
struct fence *fence)
|
||||
{
|
||||
@@ -233,6 +263,18 @@ void reservation_object_add_excl_fence(struct reservation_object *obj,
|
||||
}
|
||||
EXPORT_SYMBOL(reservation_object_add_excl_fence);
|
||||
|
||||
/**
|
||||
* reservation_object_get_fences_rcu - Get an object's shared and exclusive
|
||||
* fences without update side lock held
|
||||
* @obj: the reservation object
|
||||
* @pfence_excl: the returned exclusive fence (or NULL)
|
||||
* @pshared_count: the number of shared fences returned
|
||||
* @pshared: the array of shared fence ptrs returned (array is krealloc'd to
|
||||
* the required size, and must be freed by caller)
|
||||
*
|
||||
* RETURNS
|
||||
* Zero or -errno
|
||||
*/
|
||||
int reservation_object_get_fences_rcu(struct reservation_object *obj,
|
||||
struct fence **pfence_excl,
|
||||
unsigned *pshared_count,
|
||||
@@ -319,6 +361,18 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reservation_object_get_fences_rcu);
|
||||
|
||||
/**
|
||||
* reservation_object_wait_timeout_rcu - Wait on reservation's objects
|
||||
* shared and/or exclusive fences.
|
||||
* @obj: the reservation object
|
||||
* @wait_all: if true, wait on all fences, else wait on just exclusive fence
|
||||
* @intr: if true, do interruptible wait
|
||||
* @timeout: timeout value in jiffies or zero to return immediately
|
||||
*
|
||||
* RETURNS
|
||||
* Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or
|
||||
* greater than zer on success.
|
||||
*/
|
||||
long reservation_object_wait_timeout_rcu(struct reservation_object *obj,
|
||||
bool wait_all, bool intr,
|
||||
unsigned long timeout)
|
||||
@@ -416,6 +470,16 @@ reservation_object_test_signaled_single(struct fence *passed_fence)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* reservation_object_test_signaled_rcu - Test if a reservation object's
|
||||
* fences have been signaled.
|
||||
* @obj: the reservation object
|
||||
* @test_all: if true, test all fences, otherwise only test the exclusive
|
||||
* fence
|
||||
*
|
||||
* RETURNS
|
||||
* true if all fences signaled, else false
|
||||
*/
|
||||
bool reservation_object_test_signaled_rcu(struct reservation_object *obj,
|
||||
bool test_all)
|
||||
{
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/platform.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#define LPC32XX_GPIO_P3_INP_STATE _GPREG(0x000)
|
||||
#define LPC32XX_GPIO_P3_OUTP_SET _GPREG(0x004)
|
||||
@@ -371,61 +370,16 @@ static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin)
|
||||
|
||||
static int lpc32xx_gpio_to_irq_p01(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
return IRQ_LPC32XX_P0_P1_IRQ;
|
||||
}
|
||||
|
||||
static const char lpc32xx_gpio_to_irq_gpio_p3_table[] = {
|
||||
IRQ_LPC32XX_GPIO_00,
|
||||
IRQ_LPC32XX_GPIO_01,
|
||||
IRQ_LPC32XX_GPIO_02,
|
||||
IRQ_LPC32XX_GPIO_03,
|
||||
IRQ_LPC32XX_GPIO_04,
|
||||
IRQ_LPC32XX_GPIO_05,
|
||||
};
|
||||
|
||||
static int lpc32xx_gpio_to_irq_gpio_p3(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
if (offset < ARRAY_SIZE(lpc32xx_gpio_to_irq_gpio_p3_table))
|
||||
return lpc32xx_gpio_to_irq_gpio_p3_table[offset];
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
static const char lpc32xx_gpio_to_irq_gpi_p3_table[] = {
|
||||
IRQ_LPC32XX_GPI_00,
|
||||
IRQ_LPC32XX_GPI_01,
|
||||
IRQ_LPC32XX_GPI_02,
|
||||
IRQ_LPC32XX_GPI_03,
|
||||
IRQ_LPC32XX_GPI_04,
|
||||
IRQ_LPC32XX_GPI_05,
|
||||
IRQ_LPC32XX_GPI_06,
|
||||
IRQ_LPC32XX_GPI_07,
|
||||
IRQ_LPC32XX_GPI_08,
|
||||
IRQ_LPC32XX_GPI_09,
|
||||
-ENXIO, /* 10 */
|
||||
-ENXIO, /* 11 */
|
||||
-ENXIO, /* 12 */
|
||||
-ENXIO, /* 13 */
|
||||
-ENXIO, /* 14 */
|
||||
-ENXIO, /* 15 */
|
||||
-ENXIO, /* 16 */
|
||||
-ENXIO, /* 17 */
|
||||
-ENXIO, /* 18 */
|
||||
IRQ_LPC32XX_GPI_19,
|
||||
-ENXIO, /* 20 */
|
||||
-ENXIO, /* 21 */
|
||||
-ENXIO, /* 22 */
|
||||
-ENXIO, /* 23 */
|
||||
-ENXIO, /* 24 */
|
||||
-ENXIO, /* 25 */
|
||||
-ENXIO, /* 26 */
|
||||
-ENXIO, /* 27 */
|
||||
IRQ_LPC32XX_GPI_28,
|
||||
};
|
||||
static int lpc32xx_gpio_to_irq_gpio_p3(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
static int lpc32xx_gpio_to_irq_gpi_p3(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
if (offset < ARRAY_SIZE(lpc32xx_gpio_to_irq_gpi_p3_table))
|
||||
return lpc32xx_gpio_to_irq_gpi_p3_table[offset];
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/compat.h>
|
||||
#include <uapi/linux/gpio.h>
|
||||
|
||||
#include "gpiolib.h"
|
||||
@@ -316,7 +317,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct gpio_device *gdev = filp->private_data;
|
||||
struct gpio_chip *chip = gdev->chip;
|
||||
int __user *ip = (int __user *)arg;
|
||||
void __user *ip = (void __user *)arg;
|
||||
|
||||
/* We fail any subsequent ioctl():s when the chip is gone */
|
||||
if (!chip)
|
||||
@@ -388,6 +389,14 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static long gpio_ioctl_compat(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
return gpio_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* gpio_chrdev_open() - open the chardev for ioctl operations
|
||||
* @inode: inode for this chardev
|
||||
@@ -431,7 +440,9 @@ static const struct file_operations gpio_fileops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = noop_llseek,
|
||||
.unlocked_ioctl = gpio_ioctl,
|
||||
.compat_ioctl = gpio_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = gpio_ioctl_compat,
|
||||
#endif
|
||||
};
|
||||
|
||||
static void gpiodevice_release(struct device *dev)
|
||||
@@ -618,6 +629,8 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data)
|
||||
goto err_free_label;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&gpio_lock, flags);
|
||||
|
||||
for (i = 0; i < chip->ngpio; i++) {
|
||||
struct gpio_desc *desc = &gdev->descs[i];
|
||||
|
||||
@@ -649,8 +662,6 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data)
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&gpio_lock, flags);
|
||||
|
||||
#ifdef CONFIG_PINCTRL
|
||||
INIT_LIST_HEAD(&gdev->pin_ranges);
|
||||
#endif
|
||||
@@ -1356,10 +1367,13 @@ static int __gpiod_request(struct gpio_desc *desc, const char *label)
|
||||
/*
|
||||
* This descriptor validation needs to be inserted verbatim into each
|
||||
* function taking a descriptor, so we need to use a preprocessor
|
||||
* macro to avoid endless duplication.
|
||||
* macro to avoid endless duplication. If the desc is NULL it is an
|
||||
* optional GPIO and calls should just bail out.
|
||||
*/
|
||||
#define VALIDATE_DESC(desc) do { \
|
||||
if (!desc || !desc->gdev) { \
|
||||
if (!desc) \
|
||||
return 0; \
|
||||
if (!desc->gdev) { \
|
||||
pr_warn("%s: invalid GPIO\n", __func__); \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
@@ -1370,7 +1384,9 @@ static int __gpiod_request(struct gpio_desc *desc, const char *label)
|
||||
} } while (0)
|
||||
|
||||
#define VALIDATE_DESC_VOID(desc) do { \
|
||||
if (!desc || !desc->gdev) { \
|
||||
if (!desc) \
|
||||
return; \
|
||||
if (!desc->gdev) { \
|
||||
pr_warn("%s: invalid GPIO\n", __func__); \
|
||||
return; \
|
||||
} \
|
||||
@@ -2066,17 +2082,30 @@ EXPORT_SYMBOL_GPL(gpiod_to_irq);
|
||||
*/
|
||||
int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
if (offset >= chip->ngpio)
|
||||
return -EINVAL;
|
||||
struct gpio_desc *desc;
|
||||
|
||||
if (test_bit(FLAG_IS_OUT, &chip->gpiodev->descs[offset].flags)) {
|
||||
desc = gpiochip_get_desc(chip, offset);
|
||||
if (IS_ERR(desc))
|
||||
return PTR_ERR(desc);
|
||||
|
||||
/* Flush direction if something changed behind our back */
|
||||
if (chip->get_direction) {
|
||||
int dir = chip->get_direction(chip, offset);
|
||||
|
||||
if (dir)
|
||||
clear_bit(FLAG_IS_OUT, &desc->flags);
|
||||
else
|
||||
set_bit(FLAG_IS_OUT, &desc->flags);
|
||||
}
|
||||
|
||||
if (test_bit(FLAG_IS_OUT, &desc->flags)) {
|
||||
chip_err(chip,
|
||||
"%s: tried to flag a GPIO set as output for IRQ\n",
|
||||
__func__);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
set_bit(FLAG_USED_AS_IRQ, &chip->gpiodev->descs[offset].flags);
|
||||
set_bit(FLAG_USED_AS_IRQ, &desc->flags);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gpiochip_lock_as_irq);
|
||||
|
||||
@@ -33,8 +33,17 @@
|
||||
*
|
||||
*/
|
||||
|
||||
static void hdlcd_crtc_cleanup(struct drm_crtc *crtc)
|
||||
{
|
||||
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
|
||||
|
||||
/* stop the controller on cleanup */
|
||||
hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0);
|
||||
drm_crtc_cleanup(crtc);
|
||||
}
|
||||
|
||||
static const struct drm_crtc_funcs hdlcd_crtc_funcs = {
|
||||
.destroy = drm_crtc_cleanup,
|
||||
.destroy = hdlcd_crtc_cleanup,
|
||||
.set_config = drm_atomic_helper_set_config,
|
||||
.page_flip = drm_atomic_helper_page_flip,
|
||||
.reset = drm_atomic_helper_crtc_reset,
|
||||
@@ -97,7 +106,7 @@ static void hdlcd_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
||||
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
|
||||
struct drm_display_mode *m = &crtc->state->adjusted_mode;
|
||||
struct videomode vm;
|
||||
unsigned int polarities, line_length, err;
|
||||
unsigned int polarities, err;
|
||||
|
||||
vm.vfront_porch = m->crtc_vsync_start - m->crtc_vdisplay;
|
||||
vm.vback_porch = m->crtc_vtotal - m->crtc_vsync_end;
|
||||
@@ -113,23 +122,18 @@ static void hdlcd_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
||||
if (m->flags & DRM_MODE_FLAG_PVSYNC)
|
||||
polarities |= HDLCD_POLARITY_VSYNC;
|
||||
|
||||
line_length = crtc->primary->state->fb->pitches[0];
|
||||
|
||||
/* Allow max number of outstanding requests and largest burst size */
|
||||
hdlcd_write(hdlcd, HDLCD_REG_BUS_OPTIONS,
|
||||
HDLCD_BUS_MAX_OUTSTAND | HDLCD_BUS_BURST_16);
|
||||
|
||||
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, line_length);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_PITCH, line_length);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_COUNT, m->crtc_vdisplay - 1);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_V_DATA, m->crtc_vdisplay - 1);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_V_BACK_PORCH, vm.vback_porch - 1);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_V_FRONT_PORCH, vm.vfront_porch - 1);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_V_SYNC, vm.vsync_len - 1);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_H_DATA, m->crtc_hdisplay - 1);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_H_BACK_PORCH, vm.hback_porch - 1);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_H_FRONT_PORCH, vm.hfront_porch - 1);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_H_SYNC, vm.hsync_len - 1);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_H_DATA, m->crtc_hdisplay - 1);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_POLARITIES, polarities);
|
||||
|
||||
err = hdlcd_set_pxl_fmt(crtc);
|
||||
@@ -144,20 +148,19 @@ static void hdlcd_crtc_enable(struct drm_crtc *crtc)
|
||||
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
|
||||
|
||||
clk_prepare_enable(hdlcd->clk);
|
||||
hdlcd_crtc_mode_set_nofb(crtc);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 1);
|
||||
drm_crtc_vblank_on(crtc);
|
||||
}
|
||||
|
||||
static void hdlcd_crtc_disable(struct drm_crtc *crtc)
|
||||
{
|
||||
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
|
||||
|
||||
if (!crtc->primary->fb)
|
||||
if (!crtc->state->active)
|
||||
return;
|
||||
|
||||
clk_disable_unprepare(hdlcd->clk);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0);
|
||||
drm_crtc_vblank_off(crtc);
|
||||
clk_disable_unprepare(hdlcd->clk);
|
||||
}
|
||||
|
||||
static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc,
|
||||
@@ -179,20 +182,17 @@ static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc,
|
||||
static void hdlcd_crtc_atomic_begin(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *state)
|
||||
{
|
||||
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
|
||||
unsigned long flags;
|
||||
|
||||
if (crtc->state->event) {
|
||||
struct drm_pending_vblank_event *event = crtc->state->event;
|
||||
struct drm_pending_vblank_event *event = crtc->state->event;
|
||||
|
||||
if (event) {
|
||||
crtc->state->event = NULL;
|
||||
event->pipe = drm_crtc_index(crtc);
|
||||
|
||||
WARN_ON(drm_crtc_vblank_get(crtc) != 0);
|
||||
|
||||
spin_lock_irqsave(&crtc->dev->event_lock, flags);
|
||||
list_add_tail(&event->base.link, &hdlcd->event_list);
|
||||
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
|
||||
spin_lock_irq(&crtc->dev->event_lock);
|
||||
if (drm_crtc_vblank_get(crtc) == 0)
|
||||
drm_crtc_arm_vblank_event(crtc, event);
|
||||
else
|
||||
drm_crtc_send_vblank_event(crtc, event);
|
||||
spin_unlock_irq(&crtc->dev->event_lock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,6 +225,15 @@ static const struct drm_crtc_helper_funcs hdlcd_crtc_helper_funcs = {
|
||||
static int hdlcd_plane_atomic_check(struct drm_plane *plane,
|
||||
struct drm_plane_state *state)
|
||||
{
|
||||
u32 src_w, src_h;
|
||||
|
||||
src_w = state->src_w >> 16;
|
||||
src_h = state->src_h >> 16;
|
||||
|
||||
/* we can't do any scaling of the plane source */
|
||||
if ((src_w != state->crtc_w) || (src_h != state->crtc_h))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -233,20 +242,31 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane,
|
||||
{
|
||||
struct hdlcd_drm_private *hdlcd;
|
||||
struct drm_gem_cma_object *gem;
|
||||
unsigned int depth, bpp;
|
||||
u32 src_w, src_h, dest_w, dest_h;
|
||||
dma_addr_t scanout_start;
|
||||
|
||||
if (!plane->state->crtc || !plane->state->fb)
|
||||
if (!plane->state->fb)
|
||||
return;
|
||||
|
||||
hdlcd = crtc_to_hdlcd_priv(plane->state->crtc);
|
||||
drm_fb_get_bpp_depth(plane->state->fb->pixel_format, &depth, &bpp);
|
||||
src_w = plane->state->src_w >> 16;
|
||||
src_h = plane->state->src_h >> 16;
|
||||
dest_w = plane->state->crtc_w;
|
||||
dest_h = plane->state->crtc_h;
|
||||
gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
|
||||
scanout_start = gem->paddr;
|
||||
scanout_start = gem->paddr + plane->state->fb->offsets[0] +
|
||||
plane->state->crtc_y * plane->state->fb->pitches[0] +
|
||||
plane->state->crtc_x * bpp / 8;
|
||||
|
||||
hdlcd = plane->dev->dev_private;
|
||||
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, plane->state->fb->pitches[0]);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_PITCH, plane->state->fb->pitches[0]);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_COUNT, dest_h - 1);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_FB_BASE, scanout_start);
|
||||
}
|
||||
|
||||
static const struct drm_plane_helper_funcs hdlcd_plane_helper_funcs = {
|
||||
.prepare_fb = NULL,
|
||||
.cleanup_fb = NULL,
|
||||
.atomic_check = hdlcd_plane_atomic_check,
|
||||
.atomic_update = hdlcd_plane_atomic_update,
|
||||
};
|
||||
@@ -294,16 +314,6 @@ static struct drm_plane *hdlcd_plane_init(struct drm_device *drm)
|
||||
return plane;
|
||||
}
|
||||
|
||||
void hdlcd_crtc_suspend(struct drm_crtc *crtc)
|
||||
{
|
||||
hdlcd_crtc_disable(crtc);
|
||||
}
|
||||
|
||||
void hdlcd_crtc_resume(struct drm_crtc *crtc)
|
||||
{
|
||||
hdlcd_crtc_enable(crtc);
|
||||
}
|
||||
|
||||
int hdlcd_setup_crtc(struct drm_device *drm)
|
||||
{
|
||||
struct hdlcd_drm_private *hdlcd = drm->dev_private;
|
||||
|
||||
@@ -49,8 +49,6 @@ static int hdlcd_load(struct drm_device *drm, unsigned long flags)
|
||||
atomic_set(&hdlcd->dma_end_count, 0);
|
||||
#endif
|
||||
|
||||
INIT_LIST_HEAD(&hdlcd->event_list);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
hdlcd->mmio = devm_ioremap_resource(drm->dev, res);
|
||||
if (IS_ERR(hdlcd->mmio)) {
|
||||
@@ -84,11 +82,7 @@ static int hdlcd_load(struct drm_device *drm, unsigned long flags)
|
||||
goto setup_fail;
|
||||
}
|
||||
|
||||
pm_runtime_enable(drm->dev);
|
||||
|
||||
pm_runtime_get_sync(drm->dev);
|
||||
ret = drm_irq_install(drm, platform_get_irq(pdev, 0));
|
||||
pm_runtime_put_sync(drm->dev);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("failed to install IRQ handler\n");
|
||||
goto irq_fail;
|
||||
@@ -164,24 +158,9 @@ static irqreturn_t hdlcd_irq(int irq, void *arg)
|
||||
atomic_inc(&hdlcd->vsync_count);
|
||||
|
||||
#endif
|
||||
if (irq_status & HDLCD_INTERRUPT_VSYNC) {
|
||||
bool events_sent = false;
|
||||
unsigned long flags;
|
||||
struct drm_pending_vblank_event *e, *t;
|
||||
|
||||
if (irq_status & HDLCD_INTERRUPT_VSYNC)
|
||||
drm_crtc_handle_vblank(&hdlcd->crtc);
|
||||
|
||||
spin_lock_irqsave(&drm->event_lock, flags);
|
||||
list_for_each_entry_safe(e, t, &hdlcd->event_list, base.link) {
|
||||
list_del(&e->base.link);
|
||||
drm_crtc_send_vblank_event(&hdlcd->crtc, e);
|
||||
events_sent = true;
|
||||
}
|
||||
if (events_sent)
|
||||
drm_crtc_vblank_put(&hdlcd->crtc);
|
||||
spin_unlock_irqrestore(&drm->event_lock, flags);
|
||||
}
|
||||
|
||||
/* acknowledge interrupt(s) */
|
||||
hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, irq_status);
|
||||
|
||||
@@ -275,6 +254,7 @@ static int hdlcd_show_pxlclock(struct seq_file *m, void *arg)
|
||||
static struct drm_info_list hdlcd_debugfs_list[] = {
|
||||
{ "interrupt_count", hdlcd_show_underrun_count, 0 },
|
||||
{ "clocks", hdlcd_show_pxlclock, 0 },
|
||||
{ "fb", drm_fb_cma_debugfs_show, 0 },
|
||||
};
|
||||
|
||||
static int hdlcd_debugfs_init(struct drm_minor *minor)
|
||||
@@ -357,6 +337,8 @@ static int hdlcd_drm_bind(struct device *dev)
|
||||
return -ENOMEM;
|
||||
|
||||
drm->dev_private = hdlcd;
|
||||
dev_set_drvdata(dev, drm);
|
||||
|
||||
hdlcd_setup_mode_config(drm);
|
||||
ret = hdlcd_load(drm, 0);
|
||||
if (ret)
|
||||
@@ -366,14 +348,18 @@ static int hdlcd_drm_bind(struct device *dev)
|
||||
if (ret)
|
||||
goto err_unload;
|
||||
|
||||
dev_set_drvdata(dev, drm);
|
||||
|
||||
ret = component_bind_all(dev, drm);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to bind all components\n");
|
||||
goto err_unregister;
|
||||
}
|
||||
|
||||
ret = pm_runtime_set_active(dev);
|
||||
if (ret)
|
||||
goto err_pm_active;
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("failed to initialise vblank\n");
|
||||
@@ -399,16 +385,16 @@ static int hdlcd_drm_bind(struct device *dev)
|
||||
drm_mode_config_cleanup(drm);
|
||||
drm_vblank_cleanup(drm);
|
||||
err_vblank:
|
||||
pm_runtime_disable(drm->dev);
|
||||
err_pm_active:
|
||||
component_unbind_all(dev, drm);
|
||||
err_unregister:
|
||||
drm_dev_unregister(drm);
|
||||
err_unload:
|
||||
pm_runtime_get_sync(drm->dev);
|
||||
drm_irq_uninstall(drm);
|
||||
pm_runtime_put_sync(drm->dev);
|
||||
pm_runtime_disable(drm->dev);
|
||||
of_reserved_mem_device_release(drm->dev);
|
||||
err_free:
|
||||
dev_set_drvdata(dev, NULL);
|
||||
drm_dev_unref(drm);
|
||||
|
||||
return ret;
|
||||
@@ -495,30 +481,34 @@ MODULE_DEVICE_TABLE(of, hdlcd_of_match);
|
||||
static int __maybe_unused hdlcd_pm_suspend(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm = dev_get_drvdata(dev);
|
||||
struct drm_crtc *crtc;
|
||||
struct hdlcd_drm_private *hdlcd = drm ? drm->dev_private : NULL;
|
||||
|
||||
if (pm_runtime_suspended(dev))
|
||||
if (!hdlcd)
|
||||
return 0;
|
||||
|
||||
drm_modeset_lock_all(drm);
|
||||
list_for_each_entry(crtc, &drm->mode_config.crtc_list, head)
|
||||
hdlcd_crtc_suspend(crtc);
|
||||
drm_modeset_unlock_all(drm);
|
||||
drm_kms_helper_poll_disable(drm);
|
||||
|
||||
hdlcd->state = drm_atomic_helper_suspend(drm);
|
||||
if (IS_ERR(hdlcd->state)) {
|
||||
drm_kms_helper_poll_enable(drm);
|
||||
return PTR_ERR(hdlcd->state);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused hdlcd_pm_resume(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm = dev_get_drvdata(dev);
|
||||
struct drm_crtc *crtc;
|
||||
struct hdlcd_drm_private *hdlcd = drm ? drm->dev_private : NULL;
|
||||
|
||||
if (!pm_runtime_suspended(dev))
|
||||
if (!hdlcd)
|
||||
return 0;
|
||||
|
||||
drm_modeset_lock_all(drm);
|
||||
list_for_each_entry(crtc, &drm->mode_config.crtc_list, head)
|
||||
hdlcd_crtc_resume(crtc);
|
||||
drm_modeset_unlock_all(drm);
|
||||
drm_atomic_helper_resume(drm, hdlcd->state);
|
||||
drm_kms_helper_poll_enable(drm);
|
||||
pm_runtime_set_active(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,10 +9,9 @@ struct hdlcd_drm_private {
|
||||
void __iomem *mmio;
|
||||
struct clk *clk;
|
||||
struct drm_fbdev_cma *fbdev;
|
||||
struct drm_framebuffer *fb;
|
||||
struct list_head event_list;
|
||||
struct drm_crtc crtc;
|
||||
struct drm_plane *plane;
|
||||
struct drm_atomic_state *state;
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
atomic_t buffer_underrun_count;
|
||||
atomic_t bus_error_count;
|
||||
@@ -36,7 +35,5 @@ static inline u32 hdlcd_read(struct hdlcd_drm_private *hdlcd, unsigned int reg)
|
||||
|
||||
int hdlcd_setup_crtc(struct drm_device *dev);
|
||||
void hdlcd_set_scanout(struct hdlcd_drm_private *hdlcd);
|
||||
void hdlcd_crtc_suspend(struct drm_crtc *crtc);
|
||||
void hdlcd_crtc_resume(struct drm_crtc *crtc);
|
||||
|
||||
#endif /* __HDLCD_DRV_H__ */
|
||||
|
||||
@@ -391,12 +391,11 @@ void atmel_hlcdc_crtc_reset(struct drm_crtc *crtc)
|
||||
{
|
||||
struct atmel_hlcdc_crtc_state *state;
|
||||
|
||||
if (crtc->state && crtc->state->mode_blob)
|
||||
drm_property_unreference_blob(crtc->state->mode_blob);
|
||||
|
||||
if (crtc->state) {
|
||||
__drm_atomic_helper_crtc_destroy_state(crtc->state);
|
||||
state = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state);
|
||||
kfree(state);
|
||||
crtc->state = NULL;
|
||||
}
|
||||
|
||||
state = kzalloc(sizeof(*state), GFP_KERNEL);
|
||||
@@ -415,8 +414,9 @@ atmel_hlcdc_crtc_duplicate_state(struct drm_crtc *crtc)
|
||||
return NULL;
|
||||
|
||||
state = kmalloc(sizeof(*state), GFP_KERNEL);
|
||||
if (state)
|
||||
__drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
|
||||
if (!state)
|
||||
return NULL;
|
||||
__drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
|
||||
|
||||
cur = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state);
|
||||
state->output_mode = cur->output_mode;
|
||||
|
||||
@@ -351,6 +351,8 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
|
||||
drm_property_unreference_blob(state->mode_blob);
|
||||
state->mode_blob = NULL;
|
||||
|
||||
memset(&state->mode, 0, sizeof(state->mode));
|
||||
|
||||
if (blob) {
|
||||
if (blob->length != sizeof(struct drm_mode_modeinfo) ||
|
||||
drm_mode_convert_umode(&state->mode,
|
||||
@@ -363,7 +365,6 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
|
||||
DRM_DEBUG_ATOMIC("Set [MODE:%s] for CRTC state %p\n",
|
||||
state->mode.name, state);
|
||||
} else {
|
||||
memset(&state->mode, 0, sizeof(state->mode));
|
||||
state->enable = false;
|
||||
DRM_DEBUG_ATOMIC("Set [NOMODE] for CRTC state %p\n",
|
||||
state);
|
||||
|
||||
@@ -2821,8 +2821,6 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
|
||||
goto out;
|
||||
}
|
||||
|
||||
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
|
||||
|
||||
/*
|
||||
* Check whether the primary plane supports the fb pixel format.
|
||||
* Drivers not implementing the universal planes API use a
|
||||
@@ -4841,7 +4839,8 @@ bool drm_property_change_valid_get(struct drm_property *property,
|
||||
if (value == 0)
|
||||
return true;
|
||||
|
||||
return _object_find(property->dev, value, property->values[0]) != NULL;
|
||||
*ref = _object_find(property->dev, value, property->values[0]);
|
||||
return *ref != NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < property->num_values; i++)
|
||||
|
||||
@@ -445,7 +445,7 @@ int drm_fbdev_cma_create_with_funcs(struct drm_fb_helper *helper,
|
||||
err_fb_info_destroy:
|
||||
drm_fb_helper_release_fbi(helper);
|
||||
err_gem_free_object:
|
||||
dev->driver->gem_free_object(&obj->base);
|
||||
drm_gem_object_unreference_unlocked(&obj->base);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fbdev_cma_create_with_funcs);
|
||||
|
||||
@@ -121,7 +121,7 @@ struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
|
||||
return cma_obj;
|
||||
|
||||
error:
|
||||
drm->driver->gem_free_object(&cma_obj->base);
|
||||
drm_gem_object_unreference_unlocked(&cma_obj->base);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_create);
|
||||
@@ -162,18 +162,12 @@ drm_gem_cma_create_with_handle(struct drm_file *file_priv,
|
||||
* and handle has the id what user can see.
|
||||
*/
|
||||
ret = drm_gem_handle_create(file_priv, gem_obj, handle);
|
||||
if (ret)
|
||||
goto err_handle_create;
|
||||
|
||||
/* drop reference from allocate - handle holds it now. */
|
||||
drm_gem_object_unreference_unlocked(gem_obj);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
return cma_obj;
|
||||
|
||||
err_handle_create:
|
||||
drm->driver->gem_free_object(gem_obj);
|
||||
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1518,6 +1518,8 @@ int drm_mode_convert_umode(struct drm_display_mode *out,
|
||||
if (out->status != MODE_OK)
|
||||
goto out;
|
||||
|
||||
drm_mode_set_crtcinfo(out, CRTC_INTERLACE_HALVE_V);
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
|
||||
@@ -97,8 +97,8 @@ static struct imx_drm_crtc *imx_drm_find_crtc(struct drm_crtc *crtc)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int imx_drm_set_bus_format_pins(struct drm_encoder *encoder, u32 bus_format,
|
||||
int hsync_pin, int vsync_pin)
|
||||
int imx_drm_set_bus_config(struct drm_encoder *encoder, u32 bus_format,
|
||||
int hsync_pin, int vsync_pin, u32 bus_flags)
|
||||
{
|
||||
struct imx_drm_crtc_helper_funcs *helper;
|
||||
struct imx_drm_crtc *imx_crtc;
|
||||
@@ -110,14 +110,17 @@ int imx_drm_set_bus_format_pins(struct drm_encoder *encoder, u32 bus_format,
|
||||
helper = &imx_crtc->imx_drm_helper_funcs;
|
||||
if (helper->set_interface_pix_fmt)
|
||||
return helper->set_interface_pix_fmt(encoder->crtc,
|
||||
bus_format, hsync_pin, vsync_pin);
|
||||
bus_format, hsync_pin, vsync_pin,
|
||||
bus_flags);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(imx_drm_set_bus_format_pins);
|
||||
EXPORT_SYMBOL_GPL(imx_drm_set_bus_config);
|
||||
|
||||
int imx_drm_set_bus_format(struct drm_encoder *encoder, u32 bus_format)
|
||||
{
|
||||
return imx_drm_set_bus_format_pins(encoder, bus_format, 2, 3);
|
||||
return imx_drm_set_bus_config(encoder, bus_format, 2, 3,
|
||||
DRM_BUS_FLAG_DE_HIGH |
|
||||
DRM_BUS_FLAG_PIXDATA_NEGEDGE);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(imx_drm_set_bus_format);
|
||||
|
||||
|
||||
@@ -19,7 +19,8 @@ struct imx_drm_crtc_helper_funcs {
|
||||
int (*enable_vblank)(struct drm_crtc *crtc);
|
||||
void (*disable_vblank)(struct drm_crtc *crtc);
|
||||
int (*set_interface_pix_fmt)(struct drm_crtc *crtc,
|
||||
u32 bus_format, int hsync_pin, int vsync_pin);
|
||||
u32 bus_format, int hsync_pin, int vsync_pin,
|
||||
u32 bus_flags);
|
||||
const struct drm_crtc_helper_funcs *crtc_helper_funcs;
|
||||
const struct drm_crtc_funcs *crtc_funcs;
|
||||
};
|
||||
@@ -41,8 +42,8 @@ void imx_drm_mode_config_init(struct drm_device *drm);
|
||||
|
||||
struct drm_gem_cma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb);
|
||||
|
||||
int imx_drm_set_bus_format_pins(struct drm_encoder *encoder,
|
||||
u32 bus_format, int hsync_pin, int vsync_pin);
|
||||
int imx_drm_set_bus_config(struct drm_encoder *encoder, u32 bus_format,
|
||||
int hsync_pin, int vsync_pin, u32 bus_flags);
|
||||
int imx_drm_set_bus_format(struct drm_encoder *encoder,
|
||||
u32 bus_format);
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <video/of_display_timing.h>
|
||||
#include <video/of_videomode.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/videodev2.h>
|
||||
@@ -59,6 +60,7 @@ struct imx_ldb_channel {
|
||||
struct drm_encoder encoder;
|
||||
struct drm_panel *panel;
|
||||
struct device_node *child;
|
||||
struct i2c_adapter *ddc;
|
||||
int chno;
|
||||
void *edid;
|
||||
int edid_len;
|
||||
@@ -107,6 +109,9 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector)
|
||||
return num_modes;
|
||||
}
|
||||
|
||||
if (!imx_ldb_ch->edid && imx_ldb_ch->ddc)
|
||||
imx_ldb_ch->edid = drm_get_edid(connector, imx_ldb_ch->ddc);
|
||||
|
||||
if (imx_ldb_ch->edid) {
|
||||
drm_mode_connector_update_edid_property(connector,
|
||||
imx_ldb_ch->edid);
|
||||
@@ -553,7 +558,8 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
|
||||
|
||||
for_each_child_of_node(np, child) {
|
||||
struct imx_ldb_channel *channel;
|
||||
struct device_node *port;
|
||||
struct device_node *ddc_node;
|
||||
struct device_node *ep;
|
||||
|
||||
ret = of_property_read_u32(child, "reg", &i);
|
||||
if (ret || i < 0 || i > 1)
|
||||
@@ -576,33 +582,54 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
|
||||
* The output port is port@4 with an external 4-port mux or
|
||||
* port@2 with the internal 2-port mux.
|
||||
*/
|
||||
port = of_graph_get_port_by_id(child, imx_ldb->lvds_mux ? 4 : 2);
|
||||
if (port) {
|
||||
struct device_node *endpoint, *remote;
|
||||
ep = of_graph_get_endpoint_by_regs(child,
|
||||
imx_ldb->lvds_mux ? 4 : 2,
|
||||
-1);
|
||||
if (ep) {
|
||||
struct device_node *remote;
|
||||
|
||||
endpoint = of_get_child_by_name(port, "endpoint");
|
||||
if (endpoint) {
|
||||
remote = of_graph_get_remote_port_parent(endpoint);
|
||||
if (remote)
|
||||
channel->panel = of_drm_find_panel(remote);
|
||||
else
|
||||
return -EPROBE_DEFER;
|
||||
if (!channel->panel) {
|
||||
dev_err(dev, "panel not found: %s\n",
|
||||
remote->full_name);
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
remote = of_graph_get_remote_port_parent(ep);
|
||||
of_node_put(ep);
|
||||
if (remote)
|
||||
channel->panel = of_drm_find_panel(remote);
|
||||
else
|
||||
return -EPROBE_DEFER;
|
||||
of_node_put(remote);
|
||||
if (!channel->panel) {
|
||||
dev_err(dev, "panel not found: %s\n",
|
||||
remote->full_name);
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
}
|
||||
|
||||
edidp = of_get_property(child, "edid", &channel->edid_len);
|
||||
if (edidp) {
|
||||
channel->edid = kmemdup(edidp, channel->edid_len,
|
||||
GFP_KERNEL);
|
||||
} else if (!channel->panel) {
|
||||
ret = of_get_drm_display_mode(child, &channel->mode, 0);
|
||||
if (!ret)
|
||||
channel->mode_valid = 1;
|
||||
ddc_node = of_parse_phandle(child, "ddc-i2c-bus", 0);
|
||||
if (ddc_node) {
|
||||
channel->ddc = of_find_i2c_adapter_by_node(ddc_node);
|
||||
of_node_put(ddc_node);
|
||||
if (!channel->ddc) {
|
||||
dev_warn(dev, "failed to get ddc i2c adapter\n");
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
}
|
||||
|
||||
if (!channel->ddc) {
|
||||
/* if no DDC available, fallback to hardcoded EDID */
|
||||
dev_dbg(dev, "no ddc available\n");
|
||||
|
||||
edidp = of_get_property(child, "edid",
|
||||
&channel->edid_len);
|
||||
if (edidp) {
|
||||
channel->edid = kmemdup(edidp,
|
||||
channel->edid_len,
|
||||
GFP_KERNEL);
|
||||
} else if (!channel->panel) {
|
||||
/* fallback to display-timings node */
|
||||
ret = of_get_drm_display_mode(child,
|
||||
&channel->mode,
|
||||
OF_USE_NATIVE_MODE);
|
||||
if (!ret)
|
||||
channel->mode_valid = 1;
|
||||
}
|
||||
}
|
||||
|
||||
channel->bus_format = of_get_bus_format(dev, child);
|
||||
@@ -647,6 +674,7 @@ static void imx_ldb_unbind(struct device *dev, struct device *master,
|
||||
channel->encoder.funcs->destroy(&channel->encoder);
|
||||
|
||||
kfree(channel->edid);
|
||||
i2c_put_adapter(channel->ddc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -294,8 +294,10 @@ static void imx_tve_encoder_prepare(struct drm_encoder *encoder)
|
||||
|
||||
switch (tve->mode) {
|
||||
case TVE_MODE_VGA:
|
||||
imx_drm_set_bus_format_pins(encoder, MEDIA_BUS_FMT_GBR888_1X24,
|
||||
tve->hsync_pin, tve->vsync_pin);
|
||||
imx_drm_set_bus_config(encoder, MEDIA_BUS_FMT_GBR888_1X24,
|
||||
tve->hsync_pin, tve->vsync_pin,
|
||||
DRM_BUS_FLAG_DE_HIGH |
|
||||
DRM_BUS_FLAG_PIXDATA_NEGEDGE);
|
||||
break;
|
||||
case TVE_MODE_TVOUT:
|
||||
imx_drm_set_bus_format(encoder, MEDIA_BUS_FMT_YUV8_1X24);
|
||||
|
||||
@@ -66,6 +66,7 @@ struct ipu_crtc {
|
||||
struct ipu_flip_work *flip_work;
|
||||
int irq;
|
||||
u32 bus_format;
|
||||
u32 bus_flags;
|
||||
int di_hsync_pin;
|
||||
int di_vsync_pin;
|
||||
};
|
||||
@@ -271,8 +272,10 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
|
||||
else
|
||||
sig_cfg.clkflags = 0;
|
||||
|
||||
sig_cfg.enable_pol = 1;
|
||||
sig_cfg.clk_pol = 0;
|
||||
sig_cfg.enable_pol = !(ipu_crtc->bus_flags & DRM_BUS_FLAG_DE_LOW);
|
||||
/* Default to driving pixel data on negative clock edges */
|
||||
sig_cfg.clk_pol = !!(ipu_crtc->bus_flags &
|
||||
DRM_BUS_FLAG_PIXDATA_POSEDGE);
|
||||
sig_cfg.bus_format = ipu_crtc->bus_format;
|
||||
sig_cfg.v_to_h_sync = 0;
|
||||
sig_cfg.hsync_pin = ipu_crtc->di_hsync_pin;
|
||||
@@ -396,11 +399,12 @@ static void ipu_disable_vblank(struct drm_crtc *crtc)
|
||||
}
|
||||
|
||||
static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc,
|
||||
u32 bus_format, int hsync_pin, int vsync_pin)
|
||||
u32 bus_format, int hsync_pin, int vsync_pin, u32 bus_flags)
|
||||
{
|
||||
struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
|
||||
|
||||
ipu_crtc->bus_format = bus_format;
|
||||
ipu_crtc->bus_flags = bus_flags;
|
||||
ipu_crtc->di_hsync_pin = hsync_pin;
|
||||
ipu_crtc->di_vsync_pin = vsync_pin;
|
||||
|
||||
|
||||
@@ -38,6 +38,8 @@ static const uint32_t ipu_plane_formats[] = {
|
||||
DRM_FORMAT_RGBX8888,
|
||||
DRM_FORMAT_BGRA8888,
|
||||
DRM_FORMAT_BGRA8888,
|
||||
DRM_FORMAT_UYVY,
|
||||
DRM_FORMAT_VYUY,
|
||||
DRM_FORMAT_YUYV,
|
||||
DRM_FORMAT_YVYU,
|
||||
DRM_FORMAT_YUV420,
|
||||
@@ -428,7 +430,6 @@ static int ipu_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
if (crtc != plane->crtc)
|
||||
dev_dbg(plane->dev->dev, "crtc change: %p -> %p\n",
|
||||
plane->crtc, crtc);
|
||||
plane->crtc = crtc;
|
||||
|
||||
if (!ipu_plane->enabled)
|
||||
ipu_plane_enable(ipu_plane);
|
||||
@@ -461,7 +462,7 @@ static void ipu_plane_destroy(struct drm_plane *plane)
|
||||
kfree(ipu_plane);
|
||||
}
|
||||
|
||||
static struct drm_plane_funcs ipu_plane_funcs = {
|
||||
static const struct drm_plane_funcs ipu_plane_funcs = {
|
||||
.update_plane = ipu_update_plane,
|
||||
.disable_plane = ipu_disable_plane,
|
||||
.destroy = ipu_plane_destroy,
|
||||
|
||||
@@ -35,7 +35,6 @@ struct imx_parallel_display {
|
||||
void *edid;
|
||||
int edid_len;
|
||||
u32 bus_format;
|
||||
int mode_valid;
|
||||
struct drm_display_mode mode;
|
||||
struct drm_panel *panel;
|
||||
};
|
||||
@@ -68,17 +67,6 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector)
|
||||
num_modes = drm_add_edid_modes(connector, imxpd->edid);
|
||||
}
|
||||
|
||||
if (imxpd->mode_valid) {
|
||||
struct drm_display_mode *mode = drm_mode_create(connector->dev);
|
||||
|
||||
if (!mode)
|
||||
return -EINVAL;
|
||||
drm_mode_copy(mode, &imxpd->mode);
|
||||
mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
|
||||
drm_mode_probed_add(connector, mode);
|
||||
num_modes++;
|
||||
}
|
||||
|
||||
if (np) {
|
||||
struct drm_display_mode *mode = drm_mode_create(connector->dev);
|
||||
|
||||
@@ -115,8 +103,8 @@ static void imx_pd_encoder_dpms(struct drm_encoder *encoder, int mode)
|
||||
static void imx_pd_encoder_prepare(struct drm_encoder *encoder)
|
||||
{
|
||||
struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
|
||||
|
||||
imx_drm_set_bus_format(encoder, imxpd->bus_format);
|
||||
imx_drm_set_bus_config(encoder, imxpd->bus_format, 2, 3,
|
||||
imxpd->connector.display_info.bus_flags);
|
||||
}
|
||||
|
||||
static void imx_pd_encoder_commit(struct drm_encoder *encoder)
|
||||
@@ -203,7 +191,7 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
|
||||
{
|
||||
struct drm_device *drm = data;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct device_node *port;
|
||||
struct device_node *ep;
|
||||
const u8 *edidp;
|
||||
struct imx_parallel_display *imxpd;
|
||||
int ret;
|
||||
@@ -230,18 +218,18 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
|
||||
}
|
||||
|
||||
/* port@1 is the output port */
|
||||
port = of_graph_get_port_by_id(np, 1);
|
||||
if (port) {
|
||||
struct device_node *endpoint, *remote;
|
||||
ep = of_graph_get_endpoint_by_regs(np, 1, -1);
|
||||
if (ep) {
|
||||
struct device_node *remote;
|
||||
|
||||
endpoint = of_get_child_by_name(port, "endpoint");
|
||||
if (endpoint) {
|
||||
remote = of_graph_get_remote_port_parent(endpoint);
|
||||
if (remote)
|
||||
imxpd->panel = of_drm_find_panel(remote);
|
||||
if (!imxpd->panel)
|
||||
return -EPROBE_DEFER;
|
||||
remote = of_graph_get_remote_port_parent(ep);
|
||||
of_node_put(ep);
|
||||
if (remote) {
|
||||
imxpd->panel = of_drm_find_panel(remote);
|
||||
of_node_put(remote);
|
||||
}
|
||||
if (!imxpd->panel)
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
imxpd->dev = dev;
|
||||
|
||||
@@ -432,11 +432,6 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
|
||||
unsigned long pll_rate;
|
||||
unsigned int factor;
|
||||
|
||||
if (!dpi) {
|
||||
dev_err(dpi->dev, "invalid argument\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pix_rate = 1000UL * mode->clock;
|
||||
if (mode->clock <= 74000)
|
||||
factor = 8 * 3;
|
||||
|
||||
@@ -695,10 +695,8 @@ static void mtk_dsi_destroy_conn_enc(struct mtk_dsi *dsi)
|
||||
{
|
||||
drm_encoder_cleanup(&dsi->encoder);
|
||||
/* Skip connector cleanup if creation was delegated to the bridge */
|
||||
if (dsi->conn.dev) {
|
||||
drm_connector_unregister(&dsi->conn);
|
||||
if (dsi->conn.dev)
|
||||
drm_connector_cleanup(&dsi->conn);
|
||||
}
|
||||
}
|
||||
|
||||
static void mtk_dsi_ddp_start(struct mtk_ddp_comp *comp)
|
||||
|
||||
@@ -182,7 +182,7 @@ static int mga_g200se_set_plls(struct mga_device *mdev, long clock)
|
||||
}
|
||||
}
|
||||
|
||||
fvv = pllreffreq * testn / testm;
|
||||
fvv = pllreffreq * (n + 1) / (m + 1);
|
||||
fvv = (fvv - 800000) / 50000;
|
||||
|
||||
if (fvv > 15)
|
||||
@@ -202,6 +202,14 @@ static int mga_g200se_set_plls(struct mga_device *mdev, long clock)
|
||||
WREG_DAC(MGA1064_PIX_PLLC_M, m);
|
||||
WREG_DAC(MGA1064_PIX_PLLC_N, n);
|
||||
WREG_DAC(MGA1064_PIX_PLLC_P, p);
|
||||
|
||||
if (mdev->unique_rev_id >= 0x04) {
|
||||
WREG_DAC(0x1a, 0x09);
|
||||
msleep(20);
|
||||
WREG_DAC(0x1a, 0x01);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ config DRM_OMAP
|
||||
tristate "OMAP DRM"
|
||||
depends on DRM
|
||||
depends on ARCH_OMAP2PLUS || ARCH_MULTIPLATFORM
|
||||
select OMAP2_DSS
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_KMS_FB_HELPER
|
||||
select FB_SYS_FILLRECT
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <video/omap-panel-data.h>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
@@ -1180,15 +1180,6 @@ static int dsi_regulator_init(struct platform_device *dsidev)
|
||||
return PTR_ERR(vdds_dsi);
|
||||
}
|
||||
|
||||
if (regulator_can_change_voltage(vdds_dsi)) {
|
||||
r = regulator_set_voltage(vdds_dsi, 1800000, 1800000);
|
||||
if (r) {
|
||||
devm_regulator_put(vdds_dsi);
|
||||
DSSERR("can't set the DSI regulator voltage\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
dsi->vdds_dsi_reg = vdds_dsi;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/gfp.h>
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/component.h>
|
||||
#include <linux/of.h>
|
||||
#include <video/omapdss.h>
|
||||
#include <sound/omap-hdmi-audio.h>
|
||||
|
||||
@@ -100,7 +101,6 @@ static irqreturn_t hdmi_irq_handler(int irq, void *data)
|
||||
|
||||
static int hdmi_init_regulator(void)
|
||||
{
|
||||
int r;
|
||||
struct regulator *reg;
|
||||
|
||||
if (hdmi.vdda_reg != NULL)
|
||||
@@ -114,15 +114,6 @@ static int hdmi_init_regulator(void)
|
||||
return PTR_ERR(reg);
|
||||
}
|
||||
|
||||
if (regulator_can_change_voltage(reg)) {
|
||||
r = regulator_set_voltage(reg, 1800000, 1800000);
|
||||
if (r) {
|
||||
devm_regulator_put(reg);
|
||||
DSSWARN("can't set the regulator voltage\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
hdmi.vdda_reg = reg;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -211,7 +211,7 @@ static void hdmi_core_init(struct hdmi_core_video_config *video_cfg)
|
||||
static void hdmi_core_powerdown_disable(struct hdmi_core_data *core)
|
||||
{
|
||||
DSSDBG("Enter hdmi_core_powerdown_disable\n");
|
||||
REG_FLD_MOD(core->base, HDMI_CORE_SYS_SYS_CTRL1, 0x0, 0, 0);
|
||||
REG_FLD_MOD(core->base, HDMI_CORE_SYS_SYS_CTRL1, 0x1, 0, 0);
|
||||
}
|
||||
|
||||
static void hdmi_core_swreset_release(struct hdmi_core_data *core)
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/component.h>
|
||||
#include <linux/of.h>
|
||||
#include <video/omapdss.h>
|
||||
#include <sound/omap-hdmi-audio.h>
|
||||
|
||||
@@ -131,15 +132,6 @@ static int hdmi_init_regulator(void)
|
||||
return PTR_ERR(reg);
|
||||
}
|
||||
|
||||
if (regulator_can_change_voltage(reg)) {
|
||||
r = regulator_set_voltage(reg, 1800000, 1800000);
|
||||
if (r) {
|
||||
devm_regulator_put(reg);
|
||||
DSSWARN("can't set the regulator voltage\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
hdmi.vdda_reg = reg;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -51,8 +51,8 @@ static void hdmi_core_ddc_init(struct hdmi_core_data *core)
|
||||
{
|
||||
void __iomem *base = core->base;
|
||||
const unsigned long long iclk = 266000000; /* DSS L3 ICLK */
|
||||
const unsigned ss_scl_high = 4000; /* ns */
|
||||
const unsigned ss_scl_low = 4700; /* ns */
|
||||
const unsigned ss_scl_high = 4600; /* ns */
|
||||
const unsigned ss_scl_low = 5400; /* ns */
|
||||
const unsigned fs_scl_high = 600; /* ns */
|
||||
const unsigned fs_scl_low = 1300; /* ns */
|
||||
const unsigned sda_hold = 1000; /* ns */
|
||||
@@ -458,7 +458,7 @@ static void hdmi_core_write_avi_infoframe(struct hdmi_core_data *core,
|
||||
|
||||
c = (ptr[1] >> 6) & 0x3;
|
||||
m = (ptr[1] >> 4) & 0x3;
|
||||
r = (ptr[1] >> 0) & 0x3;
|
||||
r = (ptr[1] >> 0) & 0xf;
|
||||
|
||||
itc = (ptr[2] >> 7) & 0x1;
|
||||
ec = (ptr[2] >> 4) & 0x7;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <video/omapdss.h>
|
||||
|
||||
#include "dss.h"
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <video/omapdss.h>
|
||||
|
||||
#include "dss.h"
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h> /* platform_device() */
|
||||
#include <linux/sched.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/shmem_fs.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/pfn_t.h>
|
||||
|
||||
@@ -51,15 +51,6 @@ static void sti_crtc_disabling(struct drm_crtc *crtc)
|
||||
mixer->status = STI_MIXER_DISABLING;
|
||||
}
|
||||
|
||||
static bool sti_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
/* accept the provided drm_display_mode, do not fix it up */
|
||||
drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
sti_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
||||
{
|
||||
@@ -230,7 +221,6 @@ static void sti_crtc_atomic_flush(struct drm_crtc *crtc,
|
||||
static const struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
|
||||
.enable = sti_crtc_enable,
|
||||
.disable = sti_crtc_disabling,
|
||||
.mode_fixup = sti_crtc_mode_fixup,
|
||||
.mode_set = drm_helper_crtc_mode_set,
|
||||
.mode_set_nofb = sti_crtc_mode_set_nofb,
|
||||
.mode_set_base = drm_helper_crtc_mode_set_base,
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
#define ITS_FLAGS_CMDQ_NEEDS_FLUSHING (1ULL << 0)
|
||||
#define ITS_FLAGS_WORKAROUND_CAVIUM_22375 (1ULL << 1)
|
||||
#define ITS_FLAGS_WORKAROUND_CAVIUM_23144 (1ULL << 2)
|
||||
|
||||
#define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING (1 << 0)
|
||||
|
||||
@@ -82,6 +83,7 @@ struct its_node {
|
||||
u64 flags;
|
||||
u32 ite_size;
|
||||
u32 device_ids;
|
||||
int numa_node;
|
||||
};
|
||||
|
||||
#define ITS_ITT_ALIGN SZ_256
|
||||
@@ -613,11 +615,23 @@ static void its_unmask_irq(struct irq_data *d)
|
||||
static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
|
||||
bool force)
|
||||
{
|
||||
unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
|
||||
unsigned int cpu;
|
||||
const struct cpumask *cpu_mask = cpu_online_mask;
|
||||
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
|
||||
struct its_collection *target_col;
|
||||
u32 id = its_get_event_id(d);
|
||||
|
||||
/* lpi cannot be routed to a redistributor that is on a foreign node */
|
||||
if (its_dev->its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144) {
|
||||
if (its_dev->its->numa_node >= 0) {
|
||||
cpu_mask = cpumask_of_node(its_dev->its->numa_node);
|
||||
if (!cpumask_intersects(mask_val, cpu_mask))
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
cpu = cpumask_any_and(mask_val, cpu_mask);
|
||||
|
||||
if (cpu >= nr_cpu_ids)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -1101,6 +1115,16 @@ static void its_cpu_init_collection(void)
|
||||
list_for_each_entry(its, &its_nodes, entry) {
|
||||
u64 target;
|
||||
|
||||
/* avoid cross node collections and its mapping */
|
||||
if (its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144) {
|
||||
struct device_node *cpu_node;
|
||||
|
||||
cpu_node = of_get_cpu_node(cpu, NULL);
|
||||
if (its->numa_node != NUMA_NO_NODE &&
|
||||
its->numa_node != of_node_to_nid(cpu_node))
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* We now have to bind each collection to its target
|
||||
* redistributor.
|
||||
@@ -1351,9 +1375,14 @@ static void its_irq_domain_activate(struct irq_domain *domain,
|
||||
{
|
||||
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
|
||||
u32 event = its_get_event_id(d);
|
||||
const struct cpumask *cpu_mask = cpu_online_mask;
|
||||
|
||||
/* get the cpu_mask of local node */
|
||||
if (its_dev->its->numa_node >= 0)
|
||||
cpu_mask = cpumask_of_node(its_dev->its->numa_node);
|
||||
|
||||
/* Bind the LPI to the first possible CPU */
|
||||
its_dev->event_map.col_map[event] = cpumask_first(cpu_online_mask);
|
||||
its_dev->event_map.col_map[event] = cpumask_first(cpu_mask);
|
||||
|
||||
/* Map the GIC IRQ and event to the device */
|
||||
its_send_mapvi(its_dev, d->hwirq, event);
|
||||
@@ -1443,6 +1472,13 @@ static void __maybe_unused its_enable_quirk_cavium_22375(void *data)
|
||||
its->flags |= ITS_FLAGS_WORKAROUND_CAVIUM_22375;
|
||||
}
|
||||
|
||||
static void __maybe_unused its_enable_quirk_cavium_23144(void *data)
|
||||
{
|
||||
struct its_node *its = data;
|
||||
|
||||
its->flags |= ITS_FLAGS_WORKAROUND_CAVIUM_23144;
|
||||
}
|
||||
|
||||
static const struct gic_quirk its_quirks[] = {
|
||||
#ifdef CONFIG_CAVIUM_ERRATUM_22375
|
||||
{
|
||||
@@ -1451,6 +1487,14 @@ static const struct gic_quirk its_quirks[] = {
|
||||
.mask = 0xffff0fff,
|
||||
.init = its_enable_quirk_cavium_22375,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_CAVIUM_ERRATUM_23144
|
||||
{
|
||||
.desc = "ITS: Cavium erratum 23144",
|
||||
.iidr = 0xa100034c, /* ThunderX pass 1.x */
|
||||
.mask = 0xffff0fff,
|
||||
.init = its_enable_quirk_cavium_23144,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
}
|
||||
@@ -1514,6 +1558,7 @@ static int __init its_probe(struct device_node *node,
|
||||
its->base = its_base;
|
||||
its->phys_base = res.start;
|
||||
its->ite_size = ((readl_relaxed(its_base + GITS_TYPER) >> 4) & 0xf) + 1;
|
||||
its->numa_node = of_node_to_nid(node);
|
||||
|
||||
its->cmd_base = kzalloc(ITS_CMD_QUEUE_SZ, GFP_KERNEL);
|
||||
if (!its->cmd_base) {
|
||||
|
||||
@@ -155,7 +155,7 @@ static void gic_enable_redist(bool enable)
|
||||
|
||||
while (count--) {
|
||||
val = readl_relaxed(rbase + GICR_WAKER);
|
||||
if (enable ^ (val & GICR_WAKER_ChildrenAsleep))
|
||||
if (enable ^ (bool)(val & GICR_WAKER_ChildrenAsleep))
|
||||
break;
|
||||
cpu_relax();
|
||||
udelay(1);
|
||||
|
||||
@@ -91,7 +91,7 @@ static int pic32_set_type_edge(struct irq_data *data,
|
||||
/* set polarity for external interrupts only */
|
||||
for (i = 0; i < ARRAY_SIZE(priv->ext_irqs); i++) {
|
||||
if (priv->ext_irqs[i] == data->hwirq) {
|
||||
ret = pic32_set_ext_polarity(i + 1, flow_type);
|
||||
ret = pic32_set_ext_polarity(i, flow_type);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1276,7 +1276,7 @@ static int mmc_select_hs200(struct mmc_card *card)
|
||||
* switch to HS200 mode if bus width is set successfully.
|
||||
*/
|
||||
err = mmc_select_bus_width(card);
|
||||
if (!err) {
|
||||
if (err >= 0) {
|
||||
val = EXT_CSD_TIMING_HS200 |
|
||||
card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
|
||||
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
@@ -1583,7 +1583,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
|
||||
} else if (mmc_card_hs(card)) {
|
||||
/* Select the desired bus width optionally */
|
||||
err = mmc_select_bus_width(card);
|
||||
if (!err) {
|
||||
if (err >= 0) {
|
||||
err = mmc_select_hs_ddr(card);
|
||||
if (err)
|
||||
goto free_card;
|
||||
|
||||
@@ -970,8 +970,8 @@ static const struct sunxi_mmc_clk_delay sun9i_mmc_clk_delays[] = {
|
||||
[SDXC_CLK_400K] = { .output = 180, .sample = 180 },
|
||||
[SDXC_CLK_25M] = { .output = 180, .sample = 75 },
|
||||
[SDXC_CLK_50M] = { .output = 150, .sample = 120 },
|
||||
[SDXC_CLK_50M_DDR] = { .output = 90, .sample = 120 },
|
||||
[SDXC_CLK_50M_DDR_8BIT] = { .output = 90, .sample = 120 },
|
||||
[SDXC_CLK_50M_DDR] = { .output = 54, .sample = 36 },
|
||||
[SDXC_CLK_50M_DDR_8BIT] = { .output = 72, .sample = 72 },
|
||||
};
|
||||
|
||||
static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
|
||||
@@ -1129,11 +1129,6 @@ static int sunxi_mmc_probe(struct platform_device *pdev)
|
||||
MMC_CAP_1_8V_DDR |
|
||||
MMC_CAP_ERASE | MMC_CAP_SDIO_IRQ;
|
||||
|
||||
/* TODO MMC DDR is not working on A80 */
|
||||
if (of_device_is_compatible(pdev->dev.of_node,
|
||||
"allwinner,sun9i-a80-mmc"))
|
||||
mmc->caps &= ~MMC_CAP_1_8V_DDR;
|
||||
|
||||
ret = mmc_of_parse(mmc);
|
||||
if (ret)
|
||||
goto error_free_dma;
|
||||
|
||||
@@ -141,7 +141,7 @@ int arc_mdio_probe(struct arc_emac_priv *priv)
|
||||
priv->bus = bus;
|
||||
bus->priv = priv;
|
||||
bus->parent = priv->dev;
|
||||
bus->name = "Synopsys MII Bus",
|
||||
bus->name = "Synopsys MII Bus";
|
||||
bus->read = &arc_mdio_read;
|
||||
bus->write = &arc_mdio_write;
|
||||
bus->reset = &arc_mdio_reset;
|
||||
|
||||
@@ -96,6 +96,10 @@ struct alx_priv {
|
||||
unsigned int rx_ringsz;
|
||||
unsigned int rxbuf_size;
|
||||
|
||||
struct page *rx_page;
|
||||
unsigned int rx_page_offset;
|
||||
unsigned int rx_frag_size;
|
||||
|
||||
struct napi_struct napi;
|
||||
struct alx_tx_queue txq;
|
||||
struct alx_rx_queue rxq;
|
||||
|
||||
@@ -70,6 +70,35 @@ static void alx_free_txbuf(struct alx_priv *alx, int entry)
|
||||
}
|
||||
}
|
||||
|
||||
static struct sk_buff *alx_alloc_skb(struct alx_priv *alx, gfp_t gfp)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct page *page;
|
||||
|
||||
if (alx->rx_frag_size > PAGE_SIZE)
|
||||
return __netdev_alloc_skb(alx->dev, alx->rxbuf_size, gfp);
|
||||
|
||||
page = alx->rx_page;
|
||||
if (!page) {
|
||||
alx->rx_page = page = alloc_page(gfp);
|
||||
if (unlikely(!page))
|
||||
return NULL;
|
||||
alx->rx_page_offset = 0;
|
||||
}
|
||||
|
||||
skb = build_skb(page_address(page) + alx->rx_page_offset,
|
||||
alx->rx_frag_size);
|
||||
if (likely(skb)) {
|
||||
alx->rx_page_offset += alx->rx_frag_size;
|
||||
if (alx->rx_page_offset >= PAGE_SIZE)
|
||||
alx->rx_page = NULL;
|
||||
else
|
||||
get_page(page);
|
||||
}
|
||||
return skb;
|
||||
}
|
||||
|
||||
|
||||
static int alx_refill_rx_ring(struct alx_priv *alx, gfp_t gfp)
|
||||
{
|
||||
struct alx_rx_queue *rxq = &alx->rxq;
|
||||
@@ -86,7 +115,7 @@ static int alx_refill_rx_ring(struct alx_priv *alx, gfp_t gfp)
|
||||
while (!cur_buf->skb && next != rxq->read_idx) {
|
||||
struct alx_rfd *rfd = &rxq->rfd[cur];
|
||||
|
||||
skb = __netdev_alloc_skb(alx->dev, alx->rxbuf_size, gfp);
|
||||
skb = alx_alloc_skb(alx, gfp);
|
||||
if (!skb)
|
||||
break;
|
||||
dma = dma_map_single(&alx->hw.pdev->dev,
|
||||
@@ -124,6 +153,7 @@ static int alx_refill_rx_ring(struct alx_priv *alx, gfp_t gfp)
|
||||
alx_write_mem16(&alx->hw, ALX_RFD_PIDX, cur);
|
||||
}
|
||||
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -592,6 +622,11 @@ static void alx_free_rings(struct alx_priv *alx)
|
||||
kfree(alx->txq.bufs);
|
||||
kfree(alx->rxq.bufs);
|
||||
|
||||
if (alx->rx_page) {
|
||||
put_page(alx->rx_page);
|
||||
alx->rx_page = NULL;
|
||||
}
|
||||
|
||||
dma_free_coherent(&alx->hw.pdev->dev,
|
||||
alx->descmem.size,
|
||||
alx->descmem.virt,
|
||||
@@ -646,6 +681,7 @@ static int alx_request_irq(struct alx_priv *alx)
|
||||
alx->dev->name, alx);
|
||||
if (!err)
|
||||
goto out;
|
||||
|
||||
/* fall back to legacy interrupt */
|
||||
pci_disable_msi(alx->hw.pdev);
|
||||
}
|
||||
@@ -689,6 +725,7 @@ static int alx_init_sw(struct alx_priv *alx)
|
||||
struct pci_dev *pdev = alx->hw.pdev;
|
||||
struct alx_hw *hw = &alx->hw;
|
||||
int err;
|
||||
unsigned int head_size;
|
||||
|
||||
err = alx_identify_hw(alx);
|
||||
if (err) {
|
||||
@@ -704,7 +741,12 @@ static int alx_init_sw(struct alx_priv *alx)
|
||||
|
||||
hw->smb_timer = 400;
|
||||
hw->mtu = alx->dev->mtu;
|
||||
|
||||
alx->rxbuf_size = ALX_MAX_FRAME_LEN(hw->mtu);
|
||||
head_size = SKB_DATA_ALIGN(alx->rxbuf_size + NET_SKB_PAD) +
|
||||
SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
|
||||
alx->rx_frag_size = roundup_pow_of_two(head_size);
|
||||
|
||||
alx->tx_ringsz = 256;
|
||||
alx->rx_ringsz = 512;
|
||||
hw->imt = 200;
|
||||
@@ -806,6 +848,7 @@ static int alx_change_mtu(struct net_device *netdev, int mtu)
|
||||
{
|
||||
struct alx_priv *alx = netdev_priv(netdev);
|
||||
int max_frame = ALX_MAX_FRAME_LEN(mtu);
|
||||
unsigned int head_size;
|
||||
|
||||
if ((max_frame < ALX_MIN_FRAME_SIZE) ||
|
||||
(max_frame > ALX_MAX_FRAME_SIZE))
|
||||
@@ -817,6 +860,9 @@ static int alx_change_mtu(struct net_device *netdev, int mtu)
|
||||
netdev->mtu = mtu;
|
||||
alx->hw.mtu = mtu;
|
||||
alx->rxbuf_size = max(max_frame, ALX_DEF_RXBUF_SIZE);
|
||||
head_size = SKB_DATA_ALIGN(alx->rxbuf_size + NET_SKB_PAD) +
|
||||
SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
|
||||
alx->rx_frag_size = roundup_pow_of_two(head_size);
|
||||
netdev_update_features(netdev);
|
||||
if (netif_running(netdev))
|
||||
alx_reinit(alx);
|
||||
|
||||
@@ -13941,14 +13941,14 @@ static int bnx2x_init_one(struct pci_dev *pdev,
|
||||
bp->doorbells = bnx2x_vf_doorbells(bp);
|
||||
rc = bnx2x_vf_pci_alloc(bp);
|
||||
if (rc)
|
||||
goto init_one_exit;
|
||||
goto init_one_freemem;
|
||||
} else {
|
||||
doorbell_size = BNX2X_L2_MAX_CID(bp) * (1 << BNX2X_DB_SHIFT);
|
||||
if (doorbell_size > pci_resource_len(pdev, 2)) {
|
||||
dev_err(&bp->pdev->dev,
|
||||
"Cannot map doorbells, bar size too small, aborting\n");
|
||||
rc = -ENOMEM;
|
||||
goto init_one_exit;
|
||||
goto init_one_freemem;
|
||||
}
|
||||
bp->doorbells = ioremap_nocache(pci_resource_start(pdev, 2),
|
||||
doorbell_size);
|
||||
@@ -13957,19 +13957,19 @@ static int bnx2x_init_one(struct pci_dev *pdev,
|
||||
dev_err(&bp->pdev->dev,
|
||||
"Cannot map doorbell space, aborting\n");
|
||||
rc = -ENOMEM;
|
||||
goto init_one_exit;
|
||||
goto init_one_freemem;
|
||||
}
|
||||
|
||||
if (IS_VF(bp)) {
|
||||
rc = bnx2x_vfpf_acquire(bp, tx_count, rx_count);
|
||||
if (rc)
|
||||
goto init_one_exit;
|
||||
goto init_one_freemem;
|
||||
}
|
||||
|
||||
/* Enable SRIOV if capability found in configuration space */
|
||||
rc = bnx2x_iov_init_one(bp, int_mode, BNX2X_MAX_NUM_OF_VFS);
|
||||
if (rc)
|
||||
goto init_one_exit;
|
||||
goto init_one_freemem;
|
||||
|
||||
/* calc qm_cid_count */
|
||||
bp->qm_cid_count = bnx2x_set_qm_cid_count(bp);
|
||||
@@ -13988,7 +13988,7 @@ static int bnx2x_init_one(struct pci_dev *pdev,
|
||||
rc = bnx2x_set_int_mode(bp);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "Cannot set interrupts\n");
|
||||
goto init_one_exit;
|
||||
goto init_one_freemem;
|
||||
}
|
||||
BNX2X_DEV_INFO("set interrupts successfully\n");
|
||||
|
||||
@@ -13996,7 +13996,7 @@ static int bnx2x_init_one(struct pci_dev *pdev,
|
||||
rc = register_netdev(dev);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "Cannot register net device\n");
|
||||
goto init_one_exit;
|
||||
goto init_one_freemem;
|
||||
}
|
||||
BNX2X_DEV_INFO("device name after netdev register %s\n", dev->name);
|
||||
|
||||
@@ -14029,6 +14029,9 @@ static int bnx2x_init_one(struct pci_dev *pdev,
|
||||
|
||||
return 0;
|
||||
|
||||
init_one_freemem:
|
||||
bnx2x_free_mem_bp(bp);
|
||||
|
||||
init_one_exit:
|
||||
bnx2x_disable_pcie_error_reporting(bp);
|
||||
|
||||
|
||||
@@ -205,8 +205,10 @@ static int nps_enet_poll(struct napi_struct *napi, int budget)
|
||||
* re-adding ourselves to the poll list.
|
||||
*/
|
||||
|
||||
if (priv->tx_skb && !tx_ctrl_ct)
|
||||
if (priv->tx_skb && !tx_ctrl_ct) {
|
||||
nps_enet_reg_set(priv, NPS_ENET_REG_BUF_INT_ENABLE, 0);
|
||||
napi_reschedule(napi);
|
||||
}
|
||||
}
|
||||
|
||||
return work_done;
|
||||
|
||||
@@ -1197,10 +1197,8 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
|
||||
fec16_to_cpu(bdp->cbd_datlen),
|
||||
DMA_TO_DEVICE);
|
||||
bdp->cbd_bufaddr = cpu_to_fec32(0);
|
||||
if (!skb) {
|
||||
bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
|
||||
continue;
|
||||
}
|
||||
if (!skb)
|
||||
goto skb_done;
|
||||
|
||||
/* Check for errors. */
|
||||
if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
|
||||
@@ -1239,7 +1237,7 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
|
||||
|
||||
/* Free the sk buffer associated with this last transmit */
|
||||
dev_kfree_skb_any(skb);
|
||||
|
||||
skb_done:
|
||||
/* Make sure the update to bdp and tx_skbuff are performed
|
||||
* before dirty_tx
|
||||
*/
|
||||
|
||||
@@ -46,7 +46,6 @@ static u32 hns_nic_get_link(struct net_device *net_dev)
|
||||
u32 link_stat = priv->link;
|
||||
struct hnae_handle *h;
|
||||
|
||||
assert(priv && priv->ae_handle);
|
||||
h = priv->ae_handle;
|
||||
|
||||
if (priv->phy) {
|
||||
@@ -646,8 +645,6 @@ static void hns_nic_get_drvinfo(struct net_device *net_dev,
|
||||
{
|
||||
struct hns_nic_priv *priv = netdev_priv(net_dev);
|
||||
|
||||
assert(priv);
|
||||
|
||||
strncpy(drvinfo->version, HNAE_DRIVER_VERSION,
|
||||
sizeof(drvinfo->version));
|
||||
drvinfo->version[sizeof(drvinfo->version) - 1] = '\0';
|
||||
@@ -720,8 +717,6 @@ static int hns_set_pauseparam(struct net_device *net_dev,
|
||||
struct hnae_handle *h;
|
||||
struct hnae_ae_ops *ops;
|
||||
|
||||
assert(priv || priv->ae_handle);
|
||||
|
||||
h = priv->ae_handle;
|
||||
ops = h->dev->ops;
|
||||
|
||||
@@ -780,8 +775,6 @@ static int hns_set_coalesce(struct net_device *net_dev,
|
||||
struct hnae_ae_ops *ops;
|
||||
int ret;
|
||||
|
||||
assert(priv || priv->ae_handle);
|
||||
|
||||
ops = priv->ae_handle->dev->ops;
|
||||
|
||||
if (ec->tx_coalesce_usecs != ec->rx_coalesce_usecs)
|
||||
@@ -1111,8 +1104,6 @@ void hns_get_regs(struct net_device *net_dev, struct ethtool_regs *cmd,
|
||||
struct hns_nic_priv *priv = netdev_priv(net_dev);
|
||||
struct hnae_ae_ops *ops;
|
||||
|
||||
assert(priv || priv->ae_handle);
|
||||
|
||||
ops = priv->ae_handle->dev->ops;
|
||||
|
||||
cmd->version = HNS_CHIP_VERSION;
|
||||
@@ -1135,8 +1126,6 @@ static int hns_get_regs_len(struct net_device *net_dev)
|
||||
struct hns_nic_priv *priv = netdev_priv(net_dev);
|
||||
struct hnae_ae_ops *ops;
|
||||
|
||||
assert(priv || priv->ae_handle);
|
||||
|
||||
ops = priv->ae_handle->dev->ops;
|
||||
if (!ops->get_regs_len) {
|
||||
netdev_err(net_dev, "ops->get_regs_len is null!\n");
|
||||
|
||||
@@ -189,6 +189,7 @@ struct mvneta_bm_pool *mvneta_bm_pool_use(struct mvneta_bm *priv, u8 pool_id,
|
||||
SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
|
||||
hwbm_pool->construct = mvneta_bm_construct;
|
||||
hwbm_pool->priv = new_pool;
|
||||
spin_lock_init(&hwbm_pool->lock);
|
||||
|
||||
/* Create new pool */
|
||||
err = mvneta_bm_pool_create(priv, new_pool);
|
||||
|
||||
@@ -362,7 +362,7 @@ static void mlx4_en_get_ethtool_stats(struct net_device *dev,
|
||||
|
||||
for (i = 0; i < NUM_MAIN_STATS; i++, bitmap_iterator_inc(&it))
|
||||
if (bitmap_iterator_test(&it))
|
||||
data[index++] = ((unsigned long *)&priv->stats)[i];
|
||||
data[index++] = ((unsigned long *)&dev->stats)[i];
|
||||
|
||||
for (i = 0; i < NUM_PORT_STATS; i++, bitmap_iterator_inc(&it))
|
||||
if (bitmap_iterator_test(&it))
|
||||
|
||||
@@ -1296,15 +1296,16 @@ static void mlx4_en_tx_timeout(struct net_device *dev)
|
||||
}
|
||||
|
||||
|
||||
static struct net_device_stats *mlx4_en_get_stats(struct net_device *dev)
|
||||
static struct rtnl_link_stats64 *
|
||||
mlx4_en_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
|
||||
{
|
||||
struct mlx4_en_priv *priv = netdev_priv(dev);
|
||||
|
||||
spin_lock_bh(&priv->stats_lock);
|
||||
memcpy(&priv->ret_stats, &priv->stats, sizeof(priv->stats));
|
||||
netdev_stats_to_stats64(stats, &dev->stats);
|
||||
spin_unlock_bh(&priv->stats_lock);
|
||||
|
||||
return &priv->ret_stats;
|
||||
return stats;
|
||||
}
|
||||
|
||||
static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
|
||||
@@ -1876,7 +1877,6 @@ static void mlx4_en_clear_stats(struct net_device *dev)
|
||||
if (mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 1))
|
||||
en_dbg(HW, priv, "Failed dumping statistics\n");
|
||||
|
||||
memset(&priv->stats, 0, sizeof(priv->stats));
|
||||
memset(&priv->pstats, 0, sizeof(priv->pstats));
|
||||
memset(&priv->pkstats, 0, sizeof(priv->pkstats));
|
||||
memset(&priv->port_stats, 0, sizeof(priv->port_stats));
|
||||
@@ -1892,6 +1892,11 @@ static void mlx4_en_clear_stats(struct net_device *dev)
|
||||
priv->tx_ring[i]->bytes = 0;
|
||||
priv->tx_ring[i]->packets = 0;
|
||||
priv->tx_ring[i]->tx_csum = 0;
|
||||
priv->tx_ring[i]->tx_dropped = 0;
|
||||
priv->tx_ring[i]->queue_stopped = 0;
|
||||
priv->tx_ring[i]->wake_queue = 0;
|
||||
priv->tx_ring[i]->tso_packets = 0;
|
||||
priv->tx_ring[i]->xmit_more = 0;
|
||||
}
|
||||
for (i = 0; i < priv->rx_ring_num; i++) {
|
||||
priv->rx_ring[i]->bytes = 0;
|
||||
@@ -2482,7 +2487,7 @@ static const struct net_device_ops mlx4_netdev_ops = {
|
||||
.ndo_stop = mlx4_en_close,
|
||||
.ndo_start_xmit = mlx4_en_xmit,
|
||||
.ndo_select_queue = mlx4_en_select_queue,
|
||||
.ndo_get_stats = mlx4_en_get_stats,
|
||||
.ndo_get_stats64 = mlx4_en_get_stats64,
|
||||
.ndo_set_rx_mode = mlx4_en_set_rx_mode,
|
||||
.ndo_set_mac_address = mlx4_en_set_mac,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
@@ -2514,7 +2519,7 @@ static const struct net_device_ops mlx4_netdev_ops_master = {
|
||||
.ndo_stop = mlx4_en_close,
|
||||
.ndo_start_xmit = mlx4_en_xmit,
|
||||
.ndo_select_queue = mlx4_en_select_queue,
|
||||
.ndo_get_stats = mlx4_en_get_stats,
|
||||
.ndo_get_stats64 = mlx4_en_get_stats64,
|
||||
.ndo_set_rx_mode = mlx4_en_set_rx_mode,
|
||||
.ndo_set_mac_address = mlx4_en_set_mac,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
|
||||
@@ -152,8 +152,9 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
|
||||
struct mlx4_counter tmp_counter_stats;
|
||||
struct mlx4_en_stat_out_mbox *mlx4_en_stats;
|
||||
struct mlx4_en_stat_out_flow_control_mbox *flowstats;
|
||||
struct mlx4_en_priv *priv = netdev_priv(mdev->pndev[port]);
|
||||
struct net_device_stats *stats = &priv->stats;
|
||||
struct net_device *dev = mdev->pndev[port];
|
||||
struct mlx4_en_priv *priv = netdev_priv(dev);
|
||||
struct net_device_stats *stats = &dev->stats;
|
||||
struct mlx4_cmd_mailbox *mailbox;
|
||||
u64 in_mod = reset << 8 | port;
|
||||
int err;
|
||||
@@ -188,6 +189,7 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
|
||||
}
|
||||
stats->tx_packets = 0;
|
||||
stats->tx_bytes = 0;
|
||||
stats->tx_dropped = 0;
|
||||
priv->port_stats.tx_chksum_offload = 0;
|
||||
priv->port_stats.queue_stopped = 0;
|
||||
priv->port_stats.wake_queue = 0;
|
||||
@@ -199,6 +201,7 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
|
||||
|
||||
stats->tx_packets += ring->packets;
|
||||
stats->tx_bytes += ring->bytes;
|
||||
stats->tx_dropped += ring->tx_dropped;
|
||||
priv->port_stats.tx_chksum_offload += ring->tx_csum;
|
||||
priv->port_stats.queue_stopped += ring->queue_stopped;
|
||||
priv->port_stats.wake_queue += ring->wake_queue;
|
||||
@@ -237,21 +240,12 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
|
||||
stats->multicast = en_stats_adder(&mlx4_en_stats->MCAST_prio_0,
|
||||
&mlx4_en_stats->MCAST_prio_1,
|
||||
NUM_PRIORITIES);
|
||||
stats->collisions = 0;
|
||||
stats->rx_dropped = be32_to_cpu(mlx4_en_stats->RDROP) +
|
||||
sw_rx_dropped;
|
||||
stats->rx_length_errors = be32_to_cpu(mlx4_en_stats->RdropLength);
|
||||
stats->rx_over_errors = 0;
|
||||
stats->rx_crc_errors = be32_to_cpu(mlx4_en_stats->RCRC);
|
||||
stats->rx_frame_errors = 0;
|
||||
stats->rx_fifo_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw);
|
||||
stats->rx_missed_errors = 0;
|
||||
stats->tx_aborted_errors = 0;
|
||||
stats->tx_carrier_errors = 0;
|
||||
stats->tx_fifo_errors = 0;
|
||||
stats->tx_heartbeat_errors = 0;
|
||||
stats->tx_window_errors = 0;
|
||||
stats->tx_dropped = be32_to_cpu(mlx4_en_stats->TDROP);
|
||||
stats->tx_dropped += be32_to_cpu(mlx4_en_stats->TDROP);
|
||||
|
||||
/* RX stats */
|
||||
priv->pkstats.rx_multicast_packets = stats->multicast;
|
||||
|
||||
@@ -726,12 +726,12 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
bool inline_ok;
|
||||
u32 ring_cons;
|
||||
|
||||
if (!priv->port_up)
|
||||
goto tx_drop;
|
||||
|
||||
tx_ind = skb_get_queue_mapping(skb);
|
||||
ring = priv->tx_ring[tx_ind];
|
||||
|
||||
if (!priv->port_up)
|
||||
goto tx_drop;
|
||||
|
||||
/* fetch ring->cons far ahead before needing it to avoid stall */
|
||||
ring_cons = ACCESS_ONCE(ring->cons);
|
||||
|
||||
@@ -1030,7 +1030,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
tx_drop:
|
||||
dev_kfree_skb_any(skb);
|
||||
priv->stats.tx_dropped++;
|
||||
ring->tx_dropped++;
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -270,6 +270,7 @@ struct mlx4_en_tx_ring {
|
||||
unsigned long tx_csum;
|
||||
unsigned long tso_packets;
|
||||
unsigned long xmit_more;
|
||||
unsigned int tx_dropped;
|
||||
struct mlx4_bf bf;
|
||||
unsigned long queue_stopped;
|
||||
|
||||
@@ -482,8 +483,6 @@ struct mlx4_en_priv {
|
||||
struct mlx4_en_port_profile *prof;
|
||||
struct net_device *dev;
|
||||
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
||||
struct net_device_stats stats;
|
||||
struct net_device_stats ret_stats;
|
||||
struct mlx4_en_port_state port_state;
|
||||
spinlock_t stats_lock;
|
||||
struct ethtool_flow_id ethtool_rules[MAX_NUM_OF_FS_RULES];
|
||||
|
||||
@@ -192,9 +192,10 @@ qed_dcbx_process_tlv(struct qed_hwfn *p_hwfn,
|
||||
struct dcbx_app_priority_entry *p_tbl,
|
||||
u32 pri_tc_tbl, int count, bool dcbx_enabled)
|
||||
{
|
||||
u8 tc, priority, priority_map;
|
||||
u8 tc, priority_map;
|
||||
enum dcbx_protocol_type type;
|
||||
u16 protocol_id;
|
||||
int priority;
|
||||
bool enable;
|
||||
int i;
|
||||
|
||||
@@ -221,7 +222,7 @@ qed_dcbx_process_tlv(struct qed_hwfn *p_hwfn,
|
||||
* indication, but we only got here if there was an
|
||||
* app tlv for the protocol, so dcbx must be enabled.
|
||||
*/
|
||||
enable = !!(type == DCBX_PROTOCOL_ETH);
|
||||
enable = !(type == DCBX_PROTOCOL_ETH);
|
||||
|
||||
qed_dcbx_update_app_info(p_data, p_hwfn, enable, true,
|
||||
priority, tc, type);
|
||||
|
||||
@@ -155,12 +155,14 @@ void qed_resc_free(struct qed_dev *cdev)
|
||||
}
|
||||
}
|
||||
|
||||
static int qed_init_qm_info(struct qed_hwfn *p_hwfn)
|
||||
static int qed_init_qm_info(struct qed_hwfn *p_hwfn, bool b_sleepable)
|
||||
{
|
||||
u8 num_vports, vf_offset = 0, i, vport_id, num_ports, curr_queue = 0;
|
||||
struct qed_qm_info *qm_info = &p_hwfn->qm_info;
|
||||
struct init_qm_port_params *p_qm_port;
|
||||
u16 num_pqs, multi_cos_tcs = 1;
|
||||
u8 pf_wfq = qm_info->pf_wfq;
|
||||
u32 pf_rl = qm_info->pf_rl;
|
||||
u16 num_vfs = 0;
|
||||
|
||||
#ifdef CONFIG_QED_SRIOV
|
||||
@@ -182,23 +184,28 @@ static int qed_init_qm_info(struct qed_hwfn *p_hwfn)
|
||||
|
||||
/* PQs will be arranged as follows: First per-TC PQ then pure-LB quete.
|
||||
*/
|
||||
qm_info->qm_pq_params = kzalloc(sizeof(*qm_info->qm_pq_params) *
|
||||
num_pqs, GFP_KERNEL);
|
||||
qm_info->qm_pq_params = kcalloc(num_pqs,
|
||||
sizeof(struct init_qm_pq_params),
|
||||
b_sleepable ? GFP_KERNEL : GFP_ATOMIC);
|
||||
if (!qm_info->qm_pq_params)
|
||||
goto alloc_err;
|
||||
|
||||
qm_info->qm_vport_params = kzalloc(sizeof(*qm_info->qm_vport_params) *
|
||||
num_vports, GFP_KERNEL);
|
||||
qm_info->qm_vport_params = kcalloc(num_vports,
|
||||
sizeof(struct init_qm_vport_params),
|
||||
b_sleepable ? GFP_KERNEL
|
||||
: GFP_ATOMIC);
|
||||
if (!qm_info->qm_vport_params)
|
||||
goto alloc_err;
|
||||
|
||||
qm_info->qm_port_params = kzalloc(sizeof(*qm_info->qm_port_params) *
|
||||
MAX_NUM_PORTS, GFP_KERNEL);
|
||||
qm_info->qm_port_params = kcalloc(MAX_NUM_PORTS,
|
||||
sizeof(struct init_qm_port_params),
|
||||
b_sleepable ? GFP_KERNEL
|
||||
: GFP_ATOMIC);
|
||||
if (!qm_info->qm_port_params)
|
||||
goto alloc_err;
|
||||
|
||||
qm_info->wfq_data = kcalloc(num_vports, sizeof(*qm_info->wfq_data),
|
||||
GFP_KERNEL);
|
||||
qm_info->wfq_data = kcalloc(num_vports, sizeof(struct qed_wfq_data),
|
||||
b_sleepable ? GFP_KERNEL : GFP_ATOMIC);
|
||||
if (!qm_info->wfq_data)
|
||||
goto alloc_err;
|
||||
|
||||
@@ -264,10 +271,10 @@ static int qed_init_qm_info(struct qed_hwfn *p_hwfn)
|
||||
for (i = 0; i < qm_info->num_vports; i++)
|
||||
qm_info->qm_vport_params[i].vport_wfq = 1;
|
||||
|
||||
qm_info->pf_wfq = 0;
|
||||
qm_info->pf_rl = 0;
|
||||
qm_info->vport_rl_en = 1;
|
||||
qm_info->vport_wfq_en = 1;
|
||||
qm_info->pf_rl = pf_rl;
|
||||
qm_info->pf_wfq = pf_wfq;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -299,7 +306,7 @@ int qed_qm_reconf(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
|
||||
qed_qm_info_free(p_hwfn);
|
||||
|
||||
/* initialize qed's qm data structure */
|
||||
rc = qed_init_qm_info(p_hwfn);
|
||||
rc = qed_init_qm_info(p_hwfn, false);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@@ -388,7 +395,7 @@ int qed_resc_alloc(struct qed_dev *cdev)
|
||||
goto alloc_err;
|
||||
|
||||
/* Prepare and process QM requirements */
|
||||
rc = qed_init_qm_info(p_hwfn);
|
||||
rc = qed_init_qm_info(p_hwfn, true);
|
||||
if (rc)
|
||||
goto alloc_err;
|
||||
|
||||
@@ -581,7 +588,14 @@ static void qed_calc_hw_mode(struct qed_hwfn *p_hwfn)
|
||||
|
||||
hw_mode |= 1 << MODE_ASIC;
|
||||
|
||||
if (p_hwfn->cdev->num_hwfns > 1)
|
||||
hw_mode |= 1 << MODE_100G;
|
||||
|
||||
p_hwfn->hw_info.hw_mode = hw_mode;
|
||||
|
||||
DP_VERBOSE(p_hwfn, (NETIF_MSG_PROBE | NETIF_MSG_IFUP),
|
||||
"Configuring function for hw_mode: 0x%08x\n",
|
||||
p_hwfn->hw_info.hw_mode);
|
||||
}
|
||||
|
||||
/* Init run time data for all PFs on an engine. */
|
||||
@@ -821,6 +835,11 @@ int qed_hw_init(struct qed_dev *cdev,
|
||||
u32 load_code, param;
|
||||
int rc, mfw_rc, i;
|
||||
|
||||
if ((int_mode == QED_INT_MODE_MSI) && (cdev->num_hwfns > 1)) {
|
||||
DP_NOTICE(cdev, "MSI mode is not supported for CMT devices\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (IS_PF(cdev)) {
|
||||
rc = qed_init_fw_data(cdev, bin_fw_data);
|
||||
if (rc != 0)
|
||||
@@ -2086,6 +2105,13 @@ void qed_configure_vp_wfq_on_link_change(struct qed_dev *cdev, u32 min_pf_rate)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (cdev->num_hwfns > 1) {
|
||||
DP_VERBOSE(cdev,
|
||||
NETIF_MSG_LINK,
|
||||
"WFQ configuration is not supported for this device\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for_each_hwfn(cdev, i) {
|
||||
struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
|
||||
|
||||
|
||||
@@ -413,15 +413,17 @@ static int qed_set_int_mode(struct qed_dev *cdev, bool force_mode)
|
||||
/* Fallthrough */
|
||||
|
||||
case QED_INT_MODE_MSI:
|
||||
rc = pci_enable_msi(cdev->pdev);
|
||||
if (!rc) {
|
||||
int_params->out.int_mode = QED_INT_MODE_MSI;
|
||||
goto out;
|
||||
}
|
||||
if (cdev->num_hwfns == 1) {
|
||||
rc = pci_enable_msi(cdev->pdev);
|
||||
if (!rc) {
|
||||
int_params->out.int_mode = QED_INT_MODE_MSI;
|
||||
goto out;
|
||||
}
|
||||
|
||||
DP_NOTICE(cdev, "Failed to enable MSI\n");
|
||||
if (force_mode)
|
||||
goto out;
|
||||
DP_NOTICE(cdev, "Failed to enable MSI\n");
|
||||
if (force_mode)
|
||||
goto out;
|
||||
}
|
||||
/* Fallthrough */
|
||||
|
||||
case QED_INT_MODE_INTA:
|
||||
|
||||
@@ -230,7 +230,10 @@ static int qede_get_sset_count(struct net_device *dev, int stringset)
|
||||
case ETH_SS_PRIV_FLAGS:
|
||||
return QEDE_PRI_FLAG_LEN;
|
||||
case ETH_SS_TEST:
|
||||
return QEDE_ETHTOOL_TEST_MAX;
|
||||
if (!IS_VF(edev))
|
||||
return QEDE_ETHTOOL_TEST_MAX;
|
||||
else
|
||||
return 0;
|
||||
default:
|
||||
DP_VERBOSE(edev, QED_MSG_DEBUG,
|
||||
"Unsupported stringset 0x%08x\n", stringset);
|
||||
|
||||
@@ -1824,7 +1824,7 @@ static int qede_set_vf_rate(struct net_device *dev, int vfidx,
|
||||
{
|
||||
struct qede_dev *edev = netdev_priv(dev);
|
||||
|
||||
return edev->ops->iov->set_rate(edev->cdev, vfidx, max_tx_rate,
|
||||
return edev->ops->iov->set_rate(edev->cdev, vfidx, min_tx_rate,
|
||||
max_tx_rate);
|
||||
}
|
||||
|
||||
@@ -2091,6 +2091,29 @@ static void qede_vlan_mark_nonconfigured(struct qede_dev *edev)
|
||||
edev->accept_any_vlan = false;
|
||||
}
|
||||
|
||||
int qede_set_features(struct net_device *dev, netdev_features_t features)
|
||||
{
|
||||
struct qede_dev *edev = netdev_priv(dev);
|
||||
netdev_features_t changes = features ^ dev->features;
|
||||
bool need_reload = false;
|
||||
|
||||
/* No action needed if hardware GRO is disabled during driver load */
|
||||
if (changes & NETIF_F_GRO) {
|
||||
if (dev->features & NETIF_F_GRO)
|
||||
need_reload = !edev->gro_disable;
|
||||
else
|
||||
need_reload = edev->gro_disable;
|
||||
}
|
||||
|
||||
if (need_reload && netif_running(edev->ndev)) {
|
||||
dev->features = features;
|
||||
qede_reload(edev, NULL, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_QEDE_VXLAN
|
||||
static void qede_add_vxlan_port(struct net_device *dev,
|
||||
sa_family_t sa_family, __be16 port)
|
||||
@@ -2175,6 +2198,7 @@ static const struct net_device_ops qede_netdev_ops = {
|
||||
#endif
|
||||
.ndo_vlan_rx_add_vid = qede_vlan_rx_add_vid,
|
||||
.ndo_vlan_rx_kill_vid = qede_vlan_rx_kill_vid,
|
||||
.ndo_set_features = qede_set_features,
|
||||
.ndo_get_stats64 = qede_get_stats64,
|
||||
#ifdef CONFIG_QED_SRIOV
|
||||
.ndo_set_vf_link_state = qede_set_vf_link_state,
|
||||
|
||||
@@ -4846,7 +4846,6 @@ static void ql_eeh_close(struct net_device *ndev)
|
||||
}
|
||||
|
||||
/* Disabling the timer */
|
||||
del_timer_sync(&qdev->timer);
|
||||
ql_cancel_all_work_sync(qdev);
|
||||
|
||||
for (i = 0; i < qdev->rss_ring_count; i++)
|
||||
@@ -4873,6 +4872,7 @@ static pci_ers_result_t qlge_io_error_detected(struct pci_dev *pdev,
|
||||
return PCI_ERS_RESULT_CAN_RECOVER;
|
||||
case pci_channel_io_frozen:
|
||||
netif_device_detach(ndev);
|
||||
del_timer_sync(&qdev->timer);
|
||||
if (netif_running(ndev))
|
||||
ql_eeh_close(ndev);
|
||||
pci_disable_device(pdev);
|
||||
@@ -4880,6 +4880,7 @@ static pci_ers_result_t qlge_io_error_detected(struct pci_dev *pdev,
|
||||
case pci_channel_io_perm_failure:
|
||||
dev_err(&pdev->dev,
|
||||
"%s: pci_channel_io_perm_failure.\n", __func__);
|
||||
del_timer_sync(&qdev->timer);
|
||||
ql_eeh_close(ndev);
|
||||
set_bit(QL_EEH_FATAL, &qdev->flags);
|
||||
return PCI_ERS_RESULT_DISCONNECT;
|
||||
|
||||
@@ -619,6 +619,17 @@ static int efx_ef10_link_piobufs(struct efx_nic *efx)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void efx_ef10_forget_old_piobufs(struct efx_nic *efx)
|
||||
{
|
||||
struct efx_channel *channel;
|
||||
struct efx_tx_queue *tx_queue;
|
||||
|
||||
/* All our existing PIO buffers went away */
|
||||
efx_for_each_channel(channel, efx)
|
||||
efx_for_each_channel_tx_queue(tx_queue, channel)
|
||||
tx_queue->piobuf = NULL;
|
||||
}
|
||||
|
||||
#else /* !EFX_USE_PIO */
|
||||
|
||||
static int efx_ef10_alloc_piobufs(struct efx_nic *efx, unsigned int n)
|
||||
@@ -635,6 +646,10 @@ static void efx_ef10_free_piobufs(struct efx_nic *efx)
|
||||
{
|
||||
}
|
||||
|
||||
static void efx_ef10_forget_old_piobufs(struct efx_nic *efx)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* EFX_USE_PIO */
|
||||
|
||||
static void efx_ef10_remove(struct efx_nic *efx)
|
||||
@@ -1018,6 +1033,7 @@ static void efx_ef10_reset_mc_allocations(struct efx_nic *efx)
|
||||
nic_data->must_realloc_vis = true;
|
||||
nic_data->must_restore_filters = true;
|
||||
nic_data->must_restore_piobufs = true;
|
||||
efx_ef10_forget_old_piobufs(efx);
|
||||
nic_data->rx_rss_context = EFX_EF10_RSS_CONTEXT_INVALID;
|
||||
|
||||
/* Driver-created vswitches and vports must be re-created */
|
||||
|
||||
@@ -1726,14 +1726,33 @@ static int efx_probe_filters(struct efx_nic *efx)
|
||||
|
||||
#ifdef CONFIG_RFS_ACCEL
|
||||
if (efx->type->offload_features & NETIF_F_NTUPLE) {
|
||||
efx->rps_flow_id = kcalloc(efx->type->max_rx_ip_filters,
|
||||
sizeof(*efx->rps_flow_id),
|
||||
GFP_KERNEL);
|
||||
if (!efx->rps_flow_id) {
|
||||
struct efx_channel *channel;
|
||||
int i, success = 1;
|
||||
|
||||
efx_for_each_channel(channel, efx) {
|
||||
channel->rps_flow_id =
|
||||
kcalloc(efx->type->max_rx_ip_filters,
|
||||
sizeof(*channel->rps_flow_id),
|
||||
GFP_KERNEL);
|
||||
if (!channel->rps_flow_id)
|
||||
success = 0;
|
||||
else
|
||||
for (i = 0;
|
||||
i < efx->type->max_rx_ip_filters;
|
||||
++i)
|
||||
channel->rps_flow_id[i] =
|
||||
RPS_FLOW_ID_INVALID;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
efx_for_each_channel(channel, efx)
|
||||
kfree(channel->rps_flow_id);
|
||||
efx->type->filter_table_remove(efx);
|
||||
rc = -ENOMEM;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
efx->rps_expire_index = efx->rps_expire_channel = 0;
|
||||
}
|
||||
#endif
|
||||
out_unlock:
|
||||
@@ -1744,7 +1763,10 @@ static int efx_probe_filters(struct efx_nic *efx)
|
||||
static void efx_remove_filters(struct efx_nic *efx)
|
||||
{
|
||||
#ifdef CONFIG_RFS_ACCEL
|
||||
kfree(efx->rps_flow_id);
|
||||
struct efx_channel *channel;
|
||||
|
||||
efx_for_each_channel(channel, efx)
|
||||
kfree(channel->rps_flow_id);
|
||||
#endif
|
||||
down_write(&efx->filter_sem);
|
||||
efx->type->filter_table_remove(efx);
|
||||
|
||||
@@ -403,6 +403,8 @@ enum efx_sync_events_state {
|
||||
* @event_test_cpu: Last CPU to handle interrupt or test event for this channel
|
||||
* @irq_count: Number of IRQs since last adaptive moderation decision
|
||||
* @irq_mod_score: IRQ moderation score
|
||||
* @rps_flow_id: Flow IDs of filters allocated for accelerated RFS,
|
||||
* indexed by filter ID
|
||||
* @n_rx_tobe_disc: Count of RX_TOBE_DISC errors
|
||||
* @n_rx_ip_hdr_chksum_err: Count of RX IP header checksum errors
|
||||
* @n_rx_tcp_udp_chksum_err: Count of RX TCP and UDP checksum errors
|
||||
@@ -446,6 +448,8 @@ struct efx_channel {
|
||||
unsigned int irq_mod_score;
|
||||
#ifdef CONFIG_RFS_ACCEL
|
||||
unsigned int rfs_filters_added;
|
||||
#define RPS_FLOW_ID_INVALID 0xFFFFFFFF
|
||||
u32 *rps_flow_id;
|
||||
#endif
|
||||
|
||||
unsigned n_rx_tobe_disc;
|
||||
@@ -889,9 +893,9 @@ struct vfdi_status;
|
||||
* @filter_sem: Filter table rw_semaphore, for freeing the table
|
||||
* @filter_lock: Filter table lock, for mere content changes
|
||||
* @filter_state: Architecture-dependent filter table state
|
||||
* @rps_flow_id: Flow IDs of filters allocated for accelerated RFS,
|
||||
* indexed by filter ID
|
||||
* @rps_expire_index: Next index to check for expiry in @rps_flow_id
|
||||
* @rps_expire_channel: Next channel to check for expiry
|
||||
* @rps_expire_index: Next index to check for expiry in
|
||||
* @rps_expire_channel's @rps_flow_id
|
||||
* @active_queues: Count of RX and TX queues that haven't been flushed and drained.
|
||||
* @rxq_flush_pending: Count of number of receive queues that need to be flushed.
|
||||
* Decremented when the efx_flush_rx_queue() is called.
|
||||
@@ -1035,7 +1039,7 @@ struct efx_nic {
|
||||
spinlock_t filter_lock;
|
||||
void *filter_state;
|
||||
#ifdef CONFIG_RFS_ACCEL
|
||||
u32 *rps_flow_id;
|
||||
unsigned int rps_expire_channel;
|
||||
unsigned int rps_expire_index;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -842,33 +842,18 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
|
||||
struct efx_nic *efx = netdev_priv(net_dev);
|
||||
struct efx_channel *channel;
|
||||
struct efx_filter_spec spec;
|
||||
const __be16 *ports;
|
||||
__be16 ether_type;
|
||||
int nhoff;
|
||||
struct flow_keys fk;
|
||||
int rc;
|
||||
|
||||
/* The core RPS/RFS code has already parsed and validated
|
||||
* VLAN, IP and transport headers. We assume they are in the
|
||||
* header area.
|
||||
*/
|
||||
if (flow_id == RPS_FLOW_ID_INVALID)
|
||||
return -EINVAL;
|
||||
|
||||
if (skb->protocol == htons(ETH_P_8021Q)) {
|
||||
const struct vlan_hdr *vh =
|
||||
(const struct vlan_hdr *)skb->data;
|
||||
if (!skb_flow_dissect_flow_keys(skb, &fk, 0))
|
||||
return -EPROTONOSUPPORT;
|
||||
|
||||
/* We can't filter on the IP 5-tuple and the vlan
|
||||
* together, so just strip the vlan header and filter
|
||||
* on the IP part.
|
||||
*/
|
||||
EFX_BUG_ON_PARANOID(skb_headlen(skb) < sizeof(*vh));
|
||||
ether_type = vh->h_vlan_encapsulated_proto;
|
||||
nhoff = sizeof(struct vlan_hdr);
|
||||
} else {
|
||||
ether_type = skb->protocol;
|
||||
nhoff = 0;
|
||||
}
|
||||
|
||||
if (ether_type != htons(ETH_P_IP) && ether_type != htons(ETH_P_IPV6))
|
||||
if (fk.basic.n_proto != htons(ETH_P_IP) && fk.basic.n_proto != htons(ETH_P_IPV6))
|
||||
return -EPROTONOSUPPORT;
|
||||
if (fk.control.flags & FLOW_DIS_IS_FRAGMENT)
|
||||
return -EPROTONOSUPPORT;
|
||||
|
||||
efx_filter_init_rx(&spec, EFX_FILTER_PRI_HINT,
|
||||
@@ -878,56 +863,41 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
|
||||
EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
|
||||
EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
|
||||
EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT;
|
||||
spec.ether_type = ether_type;
|
||||
spec.ether_type = fk.basic.n_proto;
|
||||
spec.ip_proto = fk.basic.ip_proto;
|
||||
|
||||
if (ether_type == htons(ETH_P_IP)) {
|
||||
const struct iphdr *ip =
|
||||
(const struct iphdr *)(skb->data + nhoff);
|
||||
|
||||
EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + sizeof(*ip));
|
||||
if (ip_is_fragment(ip))
|
||||
return -EPROTONOSUPPORT;
|
||||
spec.ip_proto = ip->protocol;
|
||||
spec.rem_host[0] = ip->saddr;
|
||||
spec.loc_host[0] = ip->daddr;
|
||||
EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + 4 * ip->ihl + 4);
|
||||
ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl);
|
||||
if (fk.basic.n_proto == htons(ETH_P_IP)) {
|
||||
spec.rem_host[0] = fk.addrs.v4addrs.src;
|
||||
spec.loc_host[0] = fk.addrs.v4addrs.dst;
|
||||
} else {
|
||||
const struct ipv6hdr *ip6 =
|
||||
(const struct ipv6hdr *)(skb->data + nhoff);
|
||||
|
||||
EFX_BUG_ON_PARANOID(skb_headlen(skb) <
|
||||
nhoff + sizeof(*ip6) + 4);
|
||||
spec.ip_proto = ip6->nexthdr;
|
||||
memcpy(spec.rem_host, &ip6->saddr, sizeof(ip6->saddr));
|
||||
memcpy(spec.loc_host, &ip6->daddr, sizeof(ip6->daddr));
|
||||
ports = (const __be16 *)(ip6 + 1);
|
||||
memcpy(spec.rem_host, &fk.addrs.v6addrs.src, sizeof(struct in6_addr));
|
||||
memcpy(spec.loc_host, &fk.addrs.v6addrs.dst, sizeof(struct in6_addr));
|
||||
}
|
||||
|
||||
spec.rem_port = ports[0];
|
||||
spec.loc_port = ports[1];
|
||||
spec.rem_port = fk.ports.src;
|
||||
spec.loc_port = fk.ports.dst;
|
||||
|
||||
rc = efx->type->filter_rfs_insert(efx, &spec);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* Remember this so we can check whether to expire the filter later */
|
||||
efx->rps_flow_id[rc] = flow_id;
|
||||
channel = efx_get_channel(efx, skb_get_rx_queue(skb));
|
||||
channel = efx_get_channel(efx, rxq_index);
|
||||
channel->rps_flow_id[rc] = flow_id;
|
||||
++channel->rfs_filters_added;
|
||||
|
||||
if (ether_type == htons(ETH_P_IP))
|
||||
if (spec.ether_type == htons(ETH_P_IP))
|
||||
netif_info(efx, rx_status, efx->net_dev,
|
||||
"steering %s %pI4:%u:%pI4:%u to queue %u [flow %u filter %d]\n",
|
||||
(spec.ip_proto == IPPROTO_TCP) ? "TCP" : "UDP",
|
||||
spec.rem_host, ntohs(ports[0]), spec.loc_host,
|
||||
ntohs(ports[1]), rxq_index, flow_id, rc);
|
||||
spec.rem_host, ntohs(spec.rem_port), spec.loc_host,
|
||||
ntohs(spec.loc_port), rxq_index, flow_id, rc);
|
||||
else
|
||||
netif_info(efx, rx_status, efx->net_dev,
|
||||
"steering %s [%pI6]:%u:[%pI6]:%u to queue %u [flow %u filter %d]\n",
|
||||
(spec.ip_proto == IPPROTO_TCP) ? "TCP" : "UDP",
|
||||
spec.rem_host, ntohs(ports[0]), spec.loc_host,
|
||||
ntohs(ports[1]), rxq_index, flow_id, rc);
|
||||
spec.rem_host, ntohs(spec.rem_port), spec.loc_host,
|
||||
ntohs(spec.loc_port), rxq_index, flow_id, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -935,24 +905,34 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
|
||||
bool __efx_filter_rfs_expire(struct efx_nic *efx, unsigned int quota)
|
||||
{
|
||||
bool (*expire_one)(struct efx_nic *efx, u32 flow_id, unsigned int index);
|
||||
unsigned int index, size;
|
||||
unsigned int channel_idx, index, size;
|
||||
u32 flow_id;
|
||||
|
||||
if (!spin_trylock_bh(&efx->filter_lock))
|
||||
return false;
|
||||
|
||||
expire_one = efx->type->filter_rfs_expire_one;
|
||||
channel_idx = efx->rps_expire_channel;
|
||||
index = efx->rps_expire_index;
|
||||
size = efx->type->max_rx_ip_filters;
|
||||
while (quota--) {
|
||||
flow_id = efx->rps_flow_id[index];
|
||||
if (expire_one(efx, flow_id, index))
|
||||
struct efx_channel *channel = efx_get_channel(efx, channel_idx);
|
||||
flow_id = channel->rps_flow_id[index];
|
||||
|
||||
if (flow_id != RPS_FLOW_ID_INVALID &&
|
||||
expire_one(efx, flow_id, index)) {
|
||||
netif_info(efx, rx_status, efx->net_dev,
|
||||
"expired filter %d [flow %u]\n",
|
||||
index, flow_id);
|
||||
if (++index == size)
|
||||
"expired filter %d [queue %u flow %u]\n",
|
||||
index, channel_idx, flow_id);
|
||||
channel->rps_flow_id[index] = RPS_FLOW_ID_INVALID;
|
||||
}
|
||||
if (++index == size) {
|
||||
if (++channel_idx == efx->n_channels)
|
||||
channel_idx = 0;
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
efx->rps_expire_channel = channel_idx;
|
||||
efx->rps_expire_index = index;
|
||||
|
||||
spin_unlock_bh(&efx->filter_lock);
|
||||
|
||||
@@ -297,7 +297,7 @@ int stmmac_mdio_register(struct net_device *ndev)
|
||||
return -ENOMEM;
|
||||
|
||||
if (mdio_bus_data->irqs)
|
||||
memcpy(new_bus->irq, mdio_bus_data, sizeof(new_bus->irq));
|
||||
memcpy(new_bus->irq, mdio_bus_data->irqs, sizeof(new_bus->irq));
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
if (priv->device->of_node)
|
||||
|
||||
@@ -990,7 +990,7 @@ static void team_port_disable(struct team *team,
|
||||
#define TEAM_ENC_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
|
||||
NETIF_F_RXCSUM | NETIF_F_ALL_TSO)
|
||||
|
||||
static void __team_compute_features(struct team *team)
|
||||
static void ___team_compute_features(struct team *team)
|
||||
{
|
||||
struct team_port *port;
|
||||
u32 vlan_features = TEAM_VLAN_FEATURES & NETIF_F_ALL_FOR_ALL;
|
||||
@@ -1021,15 +1021,20 @@ static void __team_compute_features(struct team *team)
|
||||
team->dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
|
||||
if (dst_release_flag == (IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM))
|
||||
team->dev->priv_flags |= IFF_XMIT_DST_RELEASE;
|
||||
}
|
||||
|
||||
static void __team_compute_features(struct team *team)
|
||||
{
|
||||
___team_compute_features(team);
|
||||
netdev_change_features(team->dev);
|
||||
}
|
||||
|
||||
static void team_compute_features(struct team *team)
|
||||
{
|
||||
mutex_lock(&team->lock);
|
||||
__team_compute_features(team);
|
||||
___team_compute_features(team);
|
||||
mutex_unlock(&team->lock);
|
||||
netdev_change_features(team->dev);
|
||||
}
|
||||
|
||||
static int team_port_enter(struct team *team, struct team_port *port)
|
||||
|
||||
@@ -473,7 +473,7 @@ static void read_bulk_callback(struct urb *urb)
|
||||
goto goon;
|
||||
}
|
||||
|
||||
if (!count || count < 4)
|
||||
if (count < 4)
|
||||
goto goon;
|
||||
|
||||
rx_status = buf[count - 2];
|
||||
|
||||
@@ -61,6 +61,8 @@
|
||||
#define SUSPEND_ALLMODES (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \
|
||||
SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3)
|
||||
|
||||
#define CARRIER_CHECK_DELAY (2 * HZ)
|
||||
|
||||
struct smsc95xx_priv {
|
||||
u32 mac_cr;
|
||||
u32 hash_hi;
|
||||
@@ -69,6 +71,9 @@ struct smsc95xx_priv {
|
||||
spinlock_t mac_cr_lock;
|
||||
u8 features;
|
||||
u8 suspend_flags;
|
||||
bool link_ok;
|
||||
struct delayed_work carrier_check;
|
||||
struct usbnet *dev;
|
||||
};
|
||||
|
||||
static bool turbo_mode = true;
|
||||
@@ -624,6 +629,44 @@ static void smsc95xx_status(struct usbnet *dev, struct urb *urb)
|
||||
intdata);
|
||||
}
|
||||
|
||||
static void set_carrier(struct usbnet *dev, bool link)
|
||||
{
|
||||
struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
|
||||
|
||||
if (pdata->link_ok == link)
|
||||
return;
|
||||
|
||||
pdata->link_ok = link;
|
||||
|
||||
if (link)
|
||||
usbnet_link_change(dev, 1, 0);
|
||||
else
|
||||
usbnet_link_change(dev, 0, 0);
|
||||
}
|
||||
|
||||
static void check_carrier(struct work_struct *work)
|
||||
{
|
||||
struct smsc95xx_priv *pdata = container_of(work, struct smsc95xx_priv,
|
||||
carrier_check.work);
|
||||
struct usbnet *dev = pdata->dev;
|
||||
int ret;
|
||||
|
||||
if (pdata->suspend_flags != 0)
|
||||
return;
|
||||
|
||||
ret = smsc95xx_mdio_read(dev->net, dev->mii.phy_id, MII_BMSR);
|
||||
if (ret < 0) {
|
||||
netdev_warn(dev->net, "Failed to read MII_BMSR\n");
|
||||
return;
|
||||
}
|
||||
if (ret & BMSR_LSTATUS)
|
||||
set_carrier(dev, 1);
|
||||
else
|
||||
set_carrier(dev, 0);
|
||||
|
||||
schedule_delayed_work(&pdata->carrier_check, CARRIER_CHECK_DELAY);
|
||||
}
|
||||
|
||||
/* Enable or disable Tx & Rx checksum offload engines */
|
||||
static int smsc95xx_set_features(struct net_device *netdev,
|
||||
netdev_features_t features)
|
||||
@@ -1165,13 +1208,20 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
|
||||
dev->net->flags |= IFF_MULTICAST;
|
||||
dev->net->hard_header_len += SMSC95XX_TX_OVERHEAD_CSUM;
|
||||
dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
|
||||
|
||||
pdata->dev = dev;
|
||||
INIT_DELAYED_WORK(&pdata->carrier_check, check_carrier);
|
||||
schedule_delayed_work(&pdata->carrier_check, CARRIER_CHECK_DELAY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf)
|
||||
{
|
||||
struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
|
||||
|
||||
if (pdata) {
|
||||
cancel_delayed_work(&pdata->carrier_check);
|
||||
netif_dbg(dev, ifdown, dev->net, "free pdata\n");
|
||||
kfree(pdata);
|
||||
pdata = NULL;
|
||||
@@ -1695,6 +1745,7 @@ static int smsc95xx_resume(struct usb_interface *intf)
|
||||
|
||||
/* do this first to ensure it's cleared even in error case */
|
||||
pdata->suspend_flags = 0;
|
||||
schedule_delayed_work(&pdata->carrier_check, CARRIER_CHECK_DELAY);
|
||||
|
||||
if (suspend_flags & SUSPEND_ALLMODES) {
|
||||
/* clear wake-up sources */
|
||||
|
||||
@@ -1925,24 +1925,11 @@ static int virtnet_probe(struct virtio_device *vdev)
|
||||
|
||||
virtio_device_ready(vdev);
|
||||
|
||||
/* Last of all, set up some receive buffers. */
|
||||
for (i = 0; i < vi->curr_queue_pairs; i++) {
|
||||
try_fill_recv(vi, &vi->rq[i], GFP_KERNEL);
|
||||
|
||||
/* If we didn't even get one input buffer, we're useless. */
|
||||
if (vi->rq[i].vq->num_free ==
|
||||
virtqueue_get_vring_size(vi->rq[i].vq)) {
|
||||
free_unused_bufs(vi);
|
||||
err = -ENOMEM;
|
||||
goto free_recv_bufs;
|
||||
}
|
||||
}
|
||||
|
||||
vi->nb.notifier_call = &virtnet_cpu_callback;
|
||||
err = register_hotcpu_notifier(&vi->nb);
|
||||
if (err) {
|
||||
pr_debug("virtio_net: registering cpu notifier failed\n");
|
||||
goto free_recv_bufs;
|
||||
goto free_unregister_netdev;
|
||||
}
|
||||
|
||||
/* Assume link up if device can't report link status,
|
||||
@@ -1960,10 +1947,9 @@ static int virtnet_probe(struct virtio_device *vdev)
|
||||
|
||||
return 0;
|
||||
|
||||
free_recv_bufs:
|
||||
free_unregister_netdev:
|
||||
vi->vdev->config->reset(vdev);
|
||||
|
||||
free_receive_bufs(vi);
|
||||
unregister_netdev(dev);
|
||||
free_vqs:
|
||||
cancel_delayed_work_sync(&vi->refill);
|
||||
|
||||
@@ -3086,6 +3086,9 @@ static int vxlan_newlink(struct net *src_net, struct net_device *dev,
|
||||
if (data[IFLA_VXLAN_REMCSUM_NOPARTIAL])
|
||||
conf.flags |= VXLAN_F_REMCSUM_NOPARTIAL;
|
||||
|
||||
if (tb[IFLA_MTU])
|
||||
conf.mtu = nla_get_u32(tb[IFLA_MTU]);
|
||||
|
||||
err = vxlan_dev_configure(src_net, dev, &conf);
|
||||
switch (err) {
|
||||
case -ENODEV:
|
||||
|
||||
@@ -950,17 +950,14 @@ static int of_pmu_irq_cfg(struct arm_pmu *pmu)
|
||||
|
||||
/* For SPIs, we need to track the affinity per IRQ */
|
||||
if (using_spi) {
|
||||
if (i >= pdev->num_resources) {
|
||||
of_node_put(dn);
|
||||
if (i >= pdev->num_resources)
|
||||
break;
|
||||
}
|
||||
|
||||
irqs[i] = cpu;
|
||||
}
|
||||
|
||||
/* Keep track of the CPUs containing this PMU type */
|
||||
cpumask_set_cpu(cpu, &pmu->supported_cpus);
|
||||
of_node_put(dn);
|
||||
i++;
|
||||
} while (1);
|
||||
|
||||
@@ -995,9 +992,6 @@ int arm_pmu_device_probe(struct platform_device *pdev,
|
||||
|
||||
armpmu_init(pmu);
|
||||
|
||||
if (!__oprofile_cpu_pmu)
|
||||
__oprofile_cpu_pmu = pmu;
|
||||
|
||||
pmu->plat_device = pdev;
|
||||
|
||||
if (node && (of_id = of_match_node(of_table, pdev->dev.of_node))) {
|
||||
@@ -1033,6 +1027,9 @@ int arm_pmu_device_probe(struct platform_device *pdev,
|
||||
if (ret)
|
||||
goto out_destroy;
|
||||
|
||||
if (!__oprofile_cpu_pmu)
|
||||
__oprofile_cpu_pmu = pmu;
|
||||
|
||||
pr_info("enabled with %s PMU driver, %d counters available\n",
|
||||
pmu->name, pmu->num_events);
|
||||
|
||||
@@ -1043,6 +1040,7 @@ int arm_pmu_device_probe(struct platform_device *pdev,
|
||||
out_free:
|
||||
pr_info("%s: failed to register PMU devices!\n",
|
||||
of_node_full_name(node));
|
||||
kfree(pmu->irq_affinity);
|
||||
kfree(pmu);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1256,9 +1256,10 @@ static void mtk_eint_irq_handler(struct irq_desc *desc)
|
||||
const struct mtk_desc_pin *pin;
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
for (eint_num = 0; eint_num < pctl->devdata->ap_num; eint_num += 32) {
|
||||
for (eint_num = 0;
|
||||
eint_num < pctl->devdata->ap_num;
|
||||
eint_num += 32, reg += 4) {
|
||||
status = readl(reg);
|
||||
reg += 4;
|
||||
while (status) {
|
||||
offset = __ffs(status);
|
||||
index = eint_num + offset;
|
||||
|
||||
@@ -854,7 +854,7 @@ static int nmk_gpio_get_dir(struct gpio_chip *chip, unsigned offset)
|
||||
|
||||
clk_enable(nmk_chip->clk);
|
||||
|
||||
dir = !!(readl(nmk_chip->addr + NMK_GPIO_DIR) & BIT(offset));
|
||||
dir = !(readl(nmk_chip->addr + NMK_GPIO_DIR) & BIT(offset));
|
||||
|
||||
clk_disable(nmk_chip->clk);
|
||||
|
||||
|
||||
@@ -208,14 +208,10 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
|
||||
break;
|
||||
|
||||
case PTP_SYS_OFFSET:
|
||||
sysoff = kmalloc(sizeof(*sysoff), GFP_KERNEL);
|
||||
if (!sysoff) {
|
||||
err = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
if (copy_from_user(sysoff, (void __user *)arg,
|
||||
sizeof(*sysoff))) {
|
||||
err = -EFAULT;
|
||||
sysoff = memdup_user((void __user *)arg, sizeof(*sysoff));
|
||||
if (IS_ERR(sysoff)) {
|
||||
err = PTR_ERR(sysoff);
|
||||
sysoff = NULL;
|
||||
break;
|
||||
}
|
||||
if (sysoff->n_samples > PTP_MAX_SAMPLES) {
|
||||
|
||||
@@ -620,6 +620,11 @@ struct aac_driver_ident
|
||||
*/
|
||||
#define AAC_QUIRK_SCSI_32 0x0020
|
||||
|
||||
/*
|
||||
* SRC based adapters support the AifReqEvent functions
|
||||
*/
|
||||
#define AAC_QUIRK_SRC 0x0040
|
||||
|
||||
/*
|
||||
* The adapter interface specs all queues to be located in the same
|
||||
* physically contiguous block. The host structure that defines the
|
||||
|
||||
@@ -236,10 +236,10 @@ static struct aac_driver_ident aac_drivers[] = {
|
||||
{ aac_rx_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Catch All */
|
||||
{ aac_rkt_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Rocket Catch All */
|
||||
{ aac_nark_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec NEMER/ARK Catch All */
|
||||
{ aac_src_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec PMC Series 6 (Tupelo) */
|
||||
{ aac_srcv_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec PMC Series 7 (Denali) */
|
||||
{ aac_srcv_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec PMC Series 8 */
|
||||
{ aac_srcv_init, "aacraid", "ADAPTEC ", "RAID ", 2 } /* Adaptec PMC Series 9 */
|
||||
{ aac_src_init, "aacraid", "ADAPTEC ", "RAID ", 2, AAC_QUIRK_SRC }, /* Adaptec PMC Series 6 (Tupelo) */
|
||||
{ aac_srcv_init, "aacraid", "ADAPTEC ", "RAID ", 2, AAC_QUIRK_SRC }, /* Adaptec PMC Series 7 (Denali) */
|
||||
{ aac_srcv_init, "aacraid", "ADAPTEC ", "RAID ", 2, AAC_QUIRK_SRC }, /* Adaptec PMC Series 8 */
|
||||
{ aac_srcv_init, "aacraid", "ADAPTEC ", "RAID ", 2, AAC_QUIRK_SRC } /* Adaptec PMC Series 9 */
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1299,7 +1299,8 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
else
|
||||
shost->this_id = shost->max_id;
|
||||
|
||||
aac_intr_normal(aac, 0, 2, 0, NULL);
|
||||
if (aac_drivers[index].quirks & AAC_QUIRK_SRC)
|
||||
aac_intr_normal(aac, 0, 2, 0, NULL);
|
||||
|
||||
/*
|
||||
* dmb - we may need to move the setting of these parms somewhere else once
|
||||
|
||||
@@ -7975,13 +7975,14 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
|
||||
ActiveCableEventData =
|
||||
(Mpi26EventDataActiveCableExcept_t *) mpi_reply->EventData;
|
||||
if (ActiveCableEventData->ReasonCode ==
|
||||
MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER)
|
||||
MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER) {
|
||||
pr_info(MPT3SAS_FMT "Currently an active cable with ReceptacleID %d",
|
||||
ioc->name, ActiveCableEventData->ReceptacleID);
|
||||
pr_info("cannot be powered and devices connected to this active cable");
|
||||
pr_info("will not be seen. This active cable");
|
||||
pr_info("requires %d mW of power",
|
||||
ActiveCableEventData->ActiveCablePowerRequirement);
|
||||
}
|
||||
break;
|
||||
|
||||
default: /* ignore the rest */
|
||||
|
||||
@@ -821,9 +821,12 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
|
||||
}
|
||||
|
||||
/*
|
||||
* If we finished all bytes in the request we are done now.
|
||||
* special case: failed zero length commands always need to
|
||||
* drop down into the retry code. Otherwise, if we finished
|
||||
* all bytes in the request we are done now.
|
||||
*/
|
||||
if (!scsi_end_request(req, error, good_bytes, 0))
|
||||
if (!(blk_rq_bytes(req) == 0 && error) &&
|
||||
!scsi_end_request(req, error, good_bytes, 0))
|
||||
return;
|
||||
|
||||
/*
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user