diff options
Diffstat (limited to 'drivers/staging')
43 files changed, 1414 insertions, 192 deletions
diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index e4c8288..7a0a67f 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1865,7 +1865,6 @@ static loff_t ll_dir_seek(struct file *file, loff_t offset, int origin) int api32 = ll_need_32bit_api(sbi); loff_t ret = -EINVAL; - inode_lock(inode); switch (origin) { case SEEK_SET: break; @@ -1903,7 +1902,6 @@ static loff_t ll_dir_seek(struct file *file, loff_t offset, int origin) goto out; out: - inode_unlock(inode); return ret; } @@ -1922,7 +1920,7 @@ const struct file_operations ll_dir_operations = { .open = ll_dir_open, .release = ll_dir_release, .read = generic_read_dir, - .iterate = ll_readdir, + .iterate_shared = ll_readdir, .unlocked_ioctl = ll_dir_ioctl, .fsync = ll_fsync, }; diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index e3c0f1d..65a6ace 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -1042,8 +1042,8 @@ static inline __u64 ll_file_maxbytes(struct inode *inode) /* llite/xattr.c */ int ll_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); -ssize_t ll_getxattr(struct dentry *dentry, const char *name, - void *buffer, size_t size); +ssize_t ll_getxattr(struct dentry *dentry, struct inode *inode, + const char *name, void *buffer, size_t size); ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size); int ll_removexattr(struct dentry *dentry, const char *name); diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index 69aa15e..0c3459c 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -358,14 +358,14 @@ static ssize_t ll_direct_IO_26_seg(const struct lu_env *env, struct cl_io *io, */ #define MAX_DIO_SIZE ((KMALLOC_MAX_SIZE / sizeof(struct brw_page) * \ PAGE_SIZE) & ~(DT_MAX_BRW_SIZE - 1)) -static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter, - loff_t file_offset) +static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter) { struct lu_env *env; struct cl_io *io; struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; struct ccc_object *obj = cl_inode2ccc(inode); + loff_t file_offset = iocb->ki_pos; ssize_t count = iov_iter_count(iter); ssize_t tot_bytes = 0, result = 0; struct ll_inode_info *lli = ll_i2info(inode); diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index b68dcc9..c671f22 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -451,11 +451,9 @@ out: return rc; } -ssize_t ll_getxattr(struct dentry *dentry, const char *name, - void *buffer, size_t size) +ssize_t ll_getxattr(struct dentry *dentry, struct inode *inode, + const char *name, void *buffer, size_t size) { - struct inode *inode = d_inode(dentry); - LASSERT(inode); LASSERT(name); diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig index 0078b6a..de7e9f5 100644 --- a/drivers/staging/media/Kconfig +++ b/drivers/staging/media/Kconfig @@ -37,6 +37,8 @@ source "drivers/staging/media/omap4iss/Kconfig" source "drivers/staging/media/timb/Kconfig" +source "drivers/staging/media/tw686x-kh/Kconfig" + # Keep LIRC at the end, as it has sub-menus source "drivers/staging/media/lirc/Kconfig" diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile index 9149588..60a35b3 100644 --- a/drivers/staging/media/Makefile +++ b/drivers/staging/media/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_VIDEO_OMAP1) += omap1/ obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/ obj-$(CONFIG_DVB_MN88472) += mn88472/ obj-$(CONFIG_VIDEO_TIMBERDALE) += timb/ +obj-$(CONFIG_VIDEO_TW686X_KH) += tw686x-kh/ diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.c b/drivers/staging/media/bcm2048/radio-bcm2048.c index abf330f..8dade19 100644 --- a/drivers/staging/media/bcm2048/radio-bcm2048.c +++ b/drivers/staging/media/bcm2048/radio-bcm2048.c @@ -308,7 +308,7 @@ module_param(radio_nr, int, 0); MODULE_PARM_DESC(radio_nr, "Minor number for radio device (-1 ==> auto assign)"); -static struct region_info region_configs[] = { +static const struct region_info region_configs[] = { /* USA */ { .channel_spacing = 20, diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c index b793c04..ea3ddec 100644 --- a/drivers/staging/media/davinci_vpfe/vpfe_video.c +++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c @@ -154,7 +154,7 @@ static int vpfe_prepare_pipeline(struct vpfe_video_device *video) while ((entity = media_entity_graph_walk_next(&graph))) { if (entity == &video->video_dev.entity) continue; - if (!is_media_entity_v4l2_io(entity)) + if (!is_media_entity_v4l2_video_device(entity)) continue; far_end = to_vpfe_video(media_entity_to_video_device(entity)); if (far_end->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) @@ -172,9 +172,11 @@ static int vpfe_prepare_pipeline(struct vpfe_video_device *video) static int vpfe_update_pipe_state(struct vpfe_video_device *video) { struct vpfe_pipeline *pipe = &video->pipe; + int ret; - if (vpfe_prepare_pipeline(video)) - return vpfe_prepare_pipeline(video); + ret = vpfe_prepare_pipeline(video); + if (ret) + return ret; /* * Find out if there is any input video @@ -182,9 +184,10 @@ static int vpfe_update_pipe_state(struct vpfe_video_device *video) */ if (pipe->input_num == 0) { pipe->state = VPFE_PIPELINE_STREAM_CONTINUOUS; - if (vpfe_update_current_ext_subdev(video)) { + ret = vpfe_update_current_ext_subdev(video); + if (ret) { pr_err("Invalid external subdev\n"); - return vpfe_update_current_ext_subdev(video); + return ret; } } else { pipe->state = VPFE_PIPELINE_STREAM_SINGLESHOT; @@ -667,6 +670,7 @@ static int vpfe_enum_fmt(struct file *file, void *priv, struct v4l2_subdev *subdev; struct v4l2_format format; struct media_pad *remote; + int ret; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_fmt\n"); @@ -695,10 +699,11 @@ static int vpfe_enum_fmt(struct file *file, void *priv, sd_fmt.pad = remote->index; sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; /* get output format of remote subdev */ - if (v4l2_subdev_call(subdev, pad, get_fmt, NULL, &sd_fmt)) { + ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &sd_fmt); + if (ret) { v4l2_err(&vpfe_dev->v4l2_dev, "invalid remote subdev for video node\n"); - return v4l2_subdev_call(subdev, pad, get_fmt, NULL, &sd_fmt); + return ret; } /* convert to pix format */ mbus.code = sd_fmt.format.code; @@ -725,6 +730,7 @@ static int vpfe_s_fmt(struct file *file, void *priv, struct vpfe_video_device *video = video_drvdata(file); struct vpfe_device *vpfe_dev = video->vpfe_dev; struct v4l2_format format; + int ret; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_fmt\n"); /* If streaming is started, return error */ @@ -733,8 +739,9 @@ static int vpfe_s_fmt(struct file *file, void *priv, return -EBUSY; } /* get adjacent subdev's output pad format */ - if (__vpfe_video_get_format(video, &format)) - return __vpfe_video_get_format(video, &format); + ret = __vpfe_video_get_format(video, &format); + if (ret) + return ret; *fmt = format; video->fmt = *fmt; return 0; @@ -757,11 +764,13 @@ static int vpfe_try_fmt(struct file *file, void *priv, struct vpfe_video_device *video = video_drvdata(file); struct vpfe_device *vpfe_dev = video->vpfe_dev; struct v4l2_format format; + int ret; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_try_fmt\n"); /* get adjacent subdev's output pad format */ - if (__vpfe_video_get_format(video, &format)) - return __vpfe_video_get_format(video, &format); + ret = __vpfe_video_get_format(video, &format); + if (ret) + return ret; *fmt = format; return 0; @@ -838,8 +847,9 @@ static int vpfe_s_input(struct file *file, void *priv, unsigned int index) v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_input\n"); - if (mutex_lock_interruptible(&video->lock)) - return mutex_lock_interruptible(&video->lock); + ret = mutex_lock_interruptible(&video->lock); + if (ret) + return ret; /* * If streaming is started return device busy * error @@ -940,8 +950,9 @@ static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id std_id) v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_std\n"); /* Call decoder driver function to set the standard */ - if (mutex_lock_interruptible(&video->lock)) - return mutex_lock_interruptible(&video->lock); + ret = mutex_lock_interruptible(&video->lock); + if (ret) + return ret; sdinfo = video->current_ext_subdev; /* If streaming is started, return device busy error */ if (video->started) { @@ -1327,8 +1338,9 @@ static int vpfe_reqbufs(struct file *file, void *priv, return -EINVAL; } - if (mutex_lock_interruptible(&video->lock)) - return mutex_lock_interruptible(&video->lock); + ret = mutex_lock_interruptible(&video->lock); + if (ret) + return ret; if (video->io_usrs != 0) { v4l2_err(&vpfe_dev->v4l2_dev, "Only one IO user allowed\n"); @@ -1354,10 +1366,11 @@ static int vpfe_reqbufs(struct file *file, void *priv, q->buf_struct_size = sizeof(struct vpfe_cap_buffer); q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - if (vb2_queue_init(q)) { + ret = vb2_queue_init(q); + if (ret) { v4l2_err(&vpfe_dev->v4l2_dev, "vb2_queue_init() failed\n"); vb2_dma_contig_cleanup_ctx(vpfe_dev->pdev); - return vb2_queue_init(q); + return ret; } fh->io_allowed = 1; @@ -1533,8 +1546,9 @@ static int vpfe_streamoff(struct file *file, void *priv, return -EINVAL; } - if (mutex_lock_interruptible(&video->lock)) - return mutex_lock_interruptible(&video->lock); + ret = mutex_lock_interruptible(&video->lock); + if (ret) + return ret; vpfe_stop_capture(video); ret = vb2_streamoff(&video->buffer_queue, buf_type); diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index f54349b..cf8da23 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -223,7 +223,7 @@ iss_video_far_end(struct iss_video *video) if (entity == &video->video.entity) continue; - if (!is_media_entity_v4l2_io(entity)) + if (!is_media_entity_v4l2_video_device(entity)) continue; far_end = to_iss_video(media_entity_to_video_device(entity)); diff --git a/drivers/staging/media/tw686x-kh/Kconfig b/drivers/staging/media/tw686x-kh/Kconfig new file mode 100644 index 0000000..6264d30 --- /dev/null +++ b/drivers/staging/media/tw686x-kh/Kconfig @@ -0,0 +1,17 @@ +config VIDEO_TW686X_KH + tristate "Intersil/Techwell TW686x Video For Linux" + depends on VIDEO_DEV && PCI && VIDEO_V4L2 + depends on !(VIDEO_TW686X=y || VIDEO_TW686X=m) || COMPILE_TEST + select VIDEOBUF2_DMA_SG + help + Support for Intersil/Techwell TW686x-based frame grabber cards. + + Currently supported chips: + - TW6864 (4 video channels), + - TW6865 (4 video channels, not tested, second generation chip), + - TW6868 (8 video channels but only 4 first channels using + built-in video decoder are supported, not tested), + - TW6869 (8 video channels, second generation chip). + + To compile this driver as a module, choose M here: the module + will be named tw686x-kh. diff --git a/drivers/staging/media/tw686x-kh/Makefile b/drivers/staging/media/tw686x-kh/Makefile new file mode 100644 index 0000000..2a36a38 --- /dev/null +++ b/drivers/staging/media/tw686x-kh/Makefile @@ -0,0 +1,3 @@ +tw686x-kh-objs := tw686x-kh-core.o tw686x-kh-video.o + +obj-$(CONFIG_VIDEO_TW686X_KH) += tw686x-kh.o diff --git a/drivers/staging/media/tw686x-kh/TODO b/drivers/staging/media/tw686x-kh/TODO new file mode 100644 index 0000000..480a495 --- /dev/null +++ b/drivers/staging/media/tw686x-kh/TODO @@ -0,0 +1,6 @@ +TODO: + +- implement V4L2_FIELD_INTERLACED* mode(s). +- add audio support + +Please Cc: patches to Krzysztof Halasa <khalasa@piap.pl>. diff --git a/drivers/staging/media/tw686x-kh/tw686x-kh-core.c b/drivers/staging/media/tw686x-kh/tw686x-kh-core.c new file mode 100644 index 0000000..03b3b62 --- /dev/null +++ b/drivers/staging/media/tw686x-kh/tw686x-kh-core.c @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2015 Industrial Research Institute for Automation + * and Measurements PIAP + * + * Written by Krzysztof Ha?asa. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include "tw686x-kh.h" +#include "tw686x-kh-regs.h" + +static irqreturn_t tw686x_irq(int irq, void *dev_id) +{ + struct tw686x_dev *dev = (struct tw686x_dev *)dev_id; + u32 int_status = reg_read(dev, INT_STATUS); /* cleared on read */ + unsigned long flags; + unsigned int handled = 0; + + if (int_status) { + spin_lock_irqsave(&dev->irq_lock, flags); + dev->dma_requests |= int_status; + spin_unlock_irqrestore(&dev->irq_lock, flags); + + if (int_status & 0xFF0000FF) + handled = tw686x_kh_video_irq(dev); + } + + return IRQ_RETVAL(handled); +} + +static int tw686x_probe(struct pci_dev *pci_dev, + const struct pci_device_id *pci_id) +{ + struct tw686x_dev *dev; + int err; + + dev = devm_kzalloc(&pci_dev->dev, sizeof(*dev) + + (pci_id->driver_data & TYPE_MAX_CHANNELS) * + sizeof(dev->video_channels[0]), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + sprintf(dev->name, "TW%04X", pci_dev->device); + dev->type = pci_id->driver_data; + + pr_info("%s: PCI %s, IRQ %d, MMIO 0x%lx\n", dev->name, + pci_name(pci_dev), pci_dev->irq, + (unsigned long)pci_resource_start(pci_dev, 0)); + + dev->pci_dev = pci_dev; + if (pcim_enable_device(pci_dev)) + return -EIO; + + pci_set_master(pci_dev); + + if (pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32))) { + pr_err("%s: 32-bit PCI DMA not supported\n", dev->name); + return -EIO; + } + + err = pci_request_regions(pci_dev, dev->name); + if (err < 0) { + pr_err("%s: Unable to get MMIO region\n", dev->name); + return err; + } + + dev->mmio = pci_ioremap_bar(pci_dev, 0); + if (!dev->mmio) { + pr_err("%s: Unable to remap MMIO region\n", dev->name); + return -EIO; + } + + reg_write(dev, SYS_SOFT_RST, 0x0F); /* Reset all subsystems */ + mdelay(1); + + reg_write(dev, SRST[0], 0x3F); + if (max_channels(dev) > 4) + reg_write(dev, SRST[1], 0x3F); + reg_write(dev, DMA_CMD, 0); + reg_write(dev, DMA_CHANNEL_ENABLE, 0); + reg_write(dev, DMA_CHANNEL_TIMEOUT, 0x3EFF0FF0); + reg_write(dev, DMA_TIMER_INTERVAL, 0x38000); + reg_write(dev, DMA_CONFIG, 0xFFFFFF04); + + spin_lock_init(&dev->irq_lock); + + err = devm_request_irq(&pci_dev->dev, pci_dev->irq, tw686x_irq, + IRQF_SHARED, dev->name, dev); + if (err < 0) { + pr_err("%s: Unable to get IRQ\n", dev->name); + return err; + } + + err = tw686x_kh_video_init(dev); + if (err) + return err; + + pci_set_drvdata(pci_dev, dev); + return 0; +} + +static void tw686x_remove(struct pci_dev *pci_dev) +{ + struct tw686x_dev *dev = pci_get_drvdata(pci_dev); + + tw686x_kh_video_free(dev); +} + +/* driver_data is number of A/V channels */ +static const struct pci_device_id tw686x_pci_tbl[] = { + {PCI_DEVICE(0x1797, 0x6864), .driver_data = 4}, + /* not tested */ + {PCI_DEVICE(0x1797, 0x6865), .driver_data = 4 | TYPE_SECOND_GEN}, + /* TW6868 supports 8 A/V channels with an external TW2865 chip - + not supported by the driver */ + {PCI_DEVICE(0x1797, 0x6868), .driver_data = 4}, /* not tested */ + {PCI_DEVICE(0x1797, 0x6869), .driver_data = 8 | TYPE_SECOND_GEN}, + {} +}; + +static struct pci_driver tw686x_pci_driver = { + .name = "tw686x-kh", + .id_table = tw686x_pci_tbl, + .probe = tw686x_probe, + .remove = tw686x_remove, +}; + +MODULE_DESCRIPTION("Driver for video frame grabber cards based on Intersil/Techwell TW686[4589]"); +MODULE_AUTHOR("Krzysztof Halasa"); +MODULE_LICENSE("GPL v2"); +MODULE_DEVICE_TABLE(pci, tw686x_pci_tbl); +module_pci_driver(tw686x_pci_driver); diff --git a/drivers/staging/media/tw686x-kh/tw686x-kh-regs.h b/drivers/staging/media/tw686x-kh/tw686x-kh-regs.h new file mode 100644 index 0000000..53e1889 --- /dev/null +++ b/drivers/staging/media/tw686x-kh/tw686x-kh-regs.h @@ -0,0 +1,103 @@ +/* DMA controller registers */ +#define REG8_1(a0) ((const u16[8]) {a0, a0 + 1, a0 + 2, a0 + 3, \ + a0 + 4, a0 + 5, a0 + 6, a0 + 7}) +#define REG8_2(a0) ((const u16[8]) {a0, a0 + 2, a0 + 4, a0 + 6, \ + a0 + 8, a0 + 0xA, a0 + 0xC, a0 + 0xE}) +#define REG8_8(a0) ((const u16[8]) {a0, a0 + 8, a0 + 0x10, a0 + 0x18, \ + a0 + 0x20, a0 + 0x28, a0 + 0x30, a0 + 0x38}) +#define INT_STATUS 0x00 +#define PB_STATUS 0x01 +#define DMA_CMD 0x02 +#define VIDEO_FIFO_STATUS 0x03 +#define VIDEO_CHANNEL_ID 0x04 +#define VIDEO_PARSER_STATUS 0x05 +#define SYS_SOFT_RST 0x06 +#define DMA_PAGE_TABLE0_ADDR ((const u16[8]) {0x08, 0xD0, 0xD2, 0xD4, \ + 0xD6, 0xD8, 0xDA, 0xDC}) +#define DMA_PAGE_TABLE1_ADDR ((const u16[8]) {0x09, 0xD1, 0xD3, 0xD5, \ + 0xD7, 0xD9, 0xDB, 0xDD}) +#define DMA_CHANNEL_ENABLE 0x0A +#define DMA_CONFIG 0x0B +#define DMA_TIMER_INTERVAL 0x0C +#define DMA_CHANNEL_TIMEOUT 0x0D +#define VDMA_CHANNEL_CONFIG REG8_1(0x10) +#define ADMA_P_ADDR REG8_2(0x18) +#define ADMA_B_ADDR REG8_2(0x19) +#define DMA10_P_ADDR 0x28 /* ??? */ +#define DMA10_B_ADDR 0x29 +#define VIDEO_CONTROL1 0x2A +#define VIDEO_CONTROL2 0x2B +#define AUDIO_CONTROL1 0x2C +#define AUDIO_CONTROL2 0x2D +#define PHASE_REF 0x2E +#define GPIO_REG 0x2F +#define INTL_HBAR_CTRL REG8_1(0x30) +#define AUDIO_CONTROL3 0x38 +#define VIDEO_FIELD_CTRL REG8_1(0x39) +#define HSCALER_CTRL REG8_1(0x42) +#define VIDEO_SIZE REG8_1(0x4A) +#define VIDEO_SIZE_F2 REG8_1(0x52) +#define MD_CONF REG8_1(0x60) +#define MD_INIT REG8_1(0x68) +#define MD_MAP0 REG8_1(0x70) +#define VDMA_P_ADDR REG8_8(0x80) /* not used in DMA SG mode */ +#define VDMA_WHP REG8_8(0x81) +#define VDMA_B_ADDR REG8_8(0x82) +#define VDMA_F2_P_ADDR REG8_8(0x84) +#define VDMA_F2_WHP REG8_8(0x85) +#define VDMA_F2_B_ADDR REG8_8(0x86) +#define EP_REG_ADDR 0xFE +#define EP_REG_DATA 0xFF + +/* Video decoder registers */ +#define VDREG8(a0) ((const u16[8]) { \ + a0 + 0x000, a0 + 0x010, a0 + 0x020, a0 + 0x030, \ + a0 + 0x100, a0 + 0x110, a0 + 0x120, a0 + 0x130}) +#define VIDSTAT VDREG8(0x100) +#define BRIGHT VDREG8(0x101) +#define CONTRAST VDREG8(0x102) +#define SHARPNESS VDREG8(0x103) +#define SAT_U VDREG8(0x104) +#define SAT_V VDREG8(0x105) +#define HUE VDREG8(0x106) +#define CROP_HI VDREG8(0x107) +#define VDELAY_LO VDREG8(0x108) +#define VACTIVE_LO VDREG8(0x109) +#define HDELAY_LO VDREG8(0x10A) +#define HACTIVE_LO VDREG8(0x10B) +#define MVSN VDREG8(0x10C) +#define STATUS2 VDREG8(0x10C) +#define SDT VDREG8(0x10E) +#define SDT_EN VDREG8(0x10F) + +#define VSCALE_LO VDREG8(0x144) +#define SCALE_HI VDREG8(0x145) +#define HSCALE_LO VDREG8(0x146) +#define F2CROP_HI VDREG8(0x147) +#define F2VDELAY_LO VDREG8(0x148) +#define F2VACTIVE_LO VDREG8(0x149) +#define F2HDELAY_LO VDREG8(0x14A) +#define F2HACTIVE_LO VDREG8(0x14B) +#define F2VSCALE_LO VDREG8(0x14C) +#define F2SCALE_HI VDREG8(0x14D) +#define F2HSCALE_LO VDREG8(0x14E) +#define F2CNT VDREG8(0x14F) + +#define VDREG2(a0) ((const u16[2]) {a0, a0 + 0x100}) +#define SRST VDREG2(0x180) +#define ACNTL VDREG2(0x181) +#define ACNTL2 VDREG2(0x182) +#define CNTRL1 VDREG2(0x183) +#define CKHY VDREG2(0x184) +#define SHCOR VDREG2(0x185) +#define CORING VDREG2(0x186) +#define CLMPG VDREG2(0x187) +#define IAGC VDREG2(0x188) +#define VCTRL1 VDREG2(0x18F) +#define MISC1 VDREG2(0x194) +#define LOOP VDREG2(0x195) +#define MISC2 VDREG2(0x196) + +#define CLMD VDREG2(0x197) +#define AIGAIN ((const u16[8]) {0x1D0, 0x1D1, 0x1D2, 0x1D3, \ + 0x2D0, 0x2D1, 0x2D2, 0x2D3}) diff --git a/drivers/staging/media/tw686x-kh/tw686x-kh-video.c b/drivers/staging/media/tw686x-kh/tw686x-kh-video.c new file mode 100644 index 0000000..6ecb504 --- /dev/null +++ b/drivers/staging/media/tw686x-kh/tw686x-kh-video.c @@ -0,0 +1,821 @@ +/* + * Copyright (C) 2015 Industrial Research Institute for Automation + * and Measurements PIAP + * + * Written by Krzysztof Ha?asa. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/list.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <media/v4l2-common.h> +#include <media/v4l2-event.h> +#include "tw686x-kh.h" +#include "tw686x-kh-regs.h" + +#define MAX_SG_ENTRY_SIZE (/* 8192 - 128 */ 4096) +#define MAX_SG_DESC_COUNT 256 /* PAL 704x576 needs up to 198 4-KB pages */ + +static const struct tw686x_format formats[] = { + { + .name = "4:2:2 packed, UYVY", /* aka Y422 */ + .fourcc = V4L2_PIX_FMT_UYVY, + .mode = 0, + .depth = 16, + }, { +#if 0 + .name = "4:2:0 packed, YUV", + .mode = 1, /* non-standard */ + .depth = 12, + }, { + .name = "4:1:1 packed, YUV", + .mode = 2, /* non-standard */ + .depth = 12, + }, { +#endif + .name = "4:1:1 packed, YUV", + .fourcc = V4L2_PIX_FMT_Y41P, + .mode = 3, + .depth = 12, + }, { + .name = "15 bpp RGB", + .fourcc = V4L2_PIX_FMT_RGB555, + .mode = 4, + .depth = 16, + }, { + .name = "16 bpp RGB", + .fourcc = V4L2_PIX_FMT_RGB565, + .mode = 5, + .depth = 16, + }, { + .name = "4:2:2 packed, YUYV", + .fourcc = V4L2_PIX_FMT_YUYV, + .mode = 6, + .depth = 16, + } + /* mode 7 is "reserved" */ +}; + +static const v4l2_std_id video_standards[7] = { + V4L2_STD_NTSC, + V4L2_STD_PAL, + V4L2_STD_SECAM, + V4L2_STD_NTSC_443, + V4L2_STD_PAL_M, + V4L2_STD_PAL_N, + V4L2_STD_PAL_60, +}; + +static const struct tw686x_format *format_by_fourcc(unsigned int fourcc) +{ + unsigned int cnt; + + for (cnt = 0; cnt < ARRAY_SIZE(formats); cnt++) + if (formats[cnt].fourcc == fourcc) + return &formats[cnt]; + return NULL; +} + +static void tw686x_get_format(struct tw686x_video_channel *vc, + struct v4l2_format *f) +{ + const struct tw686x_format *format; + unsigned int width, height, height_div = 1; + + format = format_by_fourcc(f->fmt.pix.pixelformat); + if (!format) { + format = &formats[0]; + f->fmt.pix.pixelformat = format->fourcc; + } + + width = 704; + if (f->fmt.pix.width < width * 3 / 4 /* halfway */) + width /= 2; + + height = (vc->video_standard & V4L2_STD_625_50) ? 576 : 480; + if (f->fmt.pix.height < height * 3 / 4 /* halfway */) + height_div = 2; + + switch (f->fmt.pix.field) { + case V4L2_FIELD_TOP: + case V4L2_FIELD_BOTTOM: + height_div = 2; + break; + case V4L2_FIELD_SEQ_BT: + if (height_div > 1) + f->fmt.pix.field = V4L2_FIELD_BOTTOM; + break; + default: + if (height_div > 1) + f->fmt.pix.field = V4L2_FIELD_TOP; + else + f->fmt.pix.field = V4L2_FIELD_SEQ_TB; + } + height /= height_div; + + f->fmt.pix.width = width; + f->fmt.pix.height = height; + f->fmt.pix.bytesperline = f->fmt.pix.width * format->depth / 8; + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; +} + +/* video queue operations */ + +static int tw686x_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, + unsigned int *nplanes, unsigned int sizes[], + void *alloc_ctxs[]) +{ + struct tw686x_video_channel *vc = vb2_get_drv_priv(vq); + unsigned int size = vc->width * vc->height * vc->format->depth / 8; + + alloc_ctxs[0] = vc->alloc_ctx; + if (*nbuffers < 2) + *nbuffers = 2; + + if (*nplanes) + return sizes[0] < size ? -EINVAL : 0; + + sizes[0] = size; + *nplanes = 1; /* packed formats only */ + return 0; +} + +static void tw686x_buf_queue(struct vb2_buffer *vb) +{ + struct tw686x_video_channel *vc = vb2_get_drv_priv(vb->vb2_queue); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct tw686x_vb2_buf *buf; + + buf = container_of(vbuf, struct tw686x_vb2_buf, vb); + + spin_lock(&vc->qlock); + list_add_tail(&buf->list, &vc->vidq_queued); + spin_unlock(&vc->qlock); +} + +static void setup_descs(struct tw686x_video_channel *vc, unsigned int n) +{ +loop: + while (!list_empty(&vc->vidq_queued)) { + struct vdma_desc *descs = vc->sg_descs[n]; + struct tw686x_vb2_buf *buf; + struct sg_table *vbuf; + struct scatterlist *sg; + unsigned int buf_len, count = 0; + int i; + + buf = list_first_entry(&vc->vidq_queued, struct tw686x_vb2_buf, + list); + list_del(&buf->list); + + buf_len = vc->width * vc->height * vc->format->depth / 8; + if (vb2_plane_size(&buf->vb.vb2_buf, 0) < buf_len) { + pr_err("Video buffer size too small\n"); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); + goto loop; /* try another */ + } + + vbuf = vb2_dma_sg_plane_desc(&buf->vb.vb2_buf, 0); + for_each_sg(vbuf->sgl, sg, vbuf->nents, i) { + dma_addr_t phys = sg_dma_address(sg); + unsigned int len = sg_dma_len(sg); + + while (len && buf_len) { + unsigned int entry_len = min_t(unsigned int, len, + MAX_SG_ENTRY_SIZE); + entry_len = min(entry_len, buf_len); + if (count == MAX_SG_DESC_COUNT) { + pr_err("Video buffer size too fragmented\n"); + vb2_buffer_done(&buf->vb.vb2_buf, + VB2_BUF_STATE_ERROR); + goto loop; + } + descs[count].phys = cpu_to_le32(phys); + descs[count++].flags_length = + cpu_to_le32(0x40000000 /* available */ | + entry_len); + phys += entry_len; + len -= entry_len; + buf_len -= entry_len; + } + if (!buf_len) + break; + } + + /* clear the remaining entries */ + while (count < MAX_SG_DESC_COUNT) { + descs[count].phys = 0; + descs[count++].flags_length = 0; /* unavailable */ + } + + buf->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE; + vc->curr_bufs[n] = buf; + return; + } + vc->curr_bufs[n] = NULL; +} + +/* On TW6864 and TW6868, all channels share the pair of video DMA SG tables, + with 10-bit start_idx and end_idx determining start and end of frame buffer + for particular channel. + TW6868 with all its 8 channels would be problematic (only 127 SG entries per + channel) but we support only 4 channels on this chip anyway (the first + 4 channels are driven with internal video decoder, the other 4 would require + an external TW286x part). + + On TW6865 and TW6869, each channel has its own DMA SG table, with indexes + starting with 0. Both chips have complete sets of internal video decoders + (respectively 4 or 8-channel). + + All chips have separate SG tables for two video frames. */ + +static void setup_dma_cfg(struct tw686x_video_channel *vc) +{ + unsigned int field_width = 704; + unsigned int field_height = (vc->video_standard & V4L2_STD_625_50) ? + 288 : 240; + unsigned int start_idx = is_second_gen(vc->dev) ? 0 : + vc->ch * MAX_SG_DESC_COUNT; + unsigned int end_idx = start_idx + MAX_SG_DESC_COUNT - 1; + u32 dma_cfg = (0 << 30) /* input selection */ | + (1 << 29) /* field2 dropped (if any) */ | + ((vc->height < 300) << 28) /* field dropping */ | + (1 << 27) /* master */ | + (0 << 25) /* master channel (for slave only) */ | + (0 << 24) /* (no) vertical (line) decimation */ | + ((vc->width < 400) << 23) /* horizontal decimation */ | + (vc->format->mode << 20) /* output video format */ | + (end_idx << 10) /* DMA end index */ | + start_idx /* DMA start index */; + u32 reg; + + reg_write(vc->dev, VDMA_CHANNEL_CONFIG[vc->ch], dma_cfg); + reg_write(vc->dev, VIDEO_SIZE[vc->ch], (1 << 31) | (field_height << 16) + | field_width); + reg = reg_read(vc->dev, VIDEO_CONTROL1); + if (vc->video_standard & V4L2_STD_625_50) + reg |= 1 << (vc->ch + 13); + else + reg &= ~(1 << (vc->ch + 13)); + reg_write(vc->dev, VIDEO_CONTROL1, reg); +} + +static int tw686x_start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct tw686x_video_channel *vc = vb2_get_drv_priv(vq); + struct tw686x_dev *dev = vc->dev; + u32 dma_ch_mask; + unsigned int n; + + setup_dma_cfg(vc); + + /* queue video buffers if available */ + spin_lock(&vc->qlock); + for (n = 0; n < 2; n++) + setup_descs(vc, n); + spin_unlock(&vc->qlock); + + dev->video_active |= 1 << vc->ch; + vc->seq = 0; + dma_ch_mask = reg_read(dev, DMA_CHANNEL_ENABLE) | (1 << vc->ch); + reg_write(dev, DMA_CHANNEL_ENABLE, dma_ch_mask); + reg_write(dev, DMA_CMD, (1 << 31) | dma_ch_mask); + return 0; +} + +static void tw686x_stop_streaming(struct vb2_queue *vq) +{ + struct tw686x_video_channel *vc = vb2_get_drv_priv(vq); + struct tw686x_dev *dev = vc->dev; + u32 dma_ch_mask = reg_read(dev, DMA_CHANNEL_ENABLE); + u32 dma_cmd = reg_read(dev, DMA_CMD); + unsigned int n; + + dma_ch_mask &= ~(1 << vc->ch); + reg_write(dev, DMA_CHANNEL_ENABLE, dma_ch_mask); + + dev->video_active &= ~(1 << vc->ch); + + dma_cmd &= ~(1 << vc->ch); + reg_write(dev, DMA_CMD, dma_cmd); + + if (!dev->video_active) { + reg_write(dev, DMA_CMD, 0); + reg_write(dev, DMA_CHANNEL_ENABLE, 0); + } + + spin_lock(&vc->qlock); + while (!list_empty(&vc->vidq_queued)) { + struct tw686x_vb2_buf *buf; + + buf = list_entry(vc->vidq_queued.next, struct tw686x_vb2_buf, + list); + list_del(&buf->list); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); + } + + for (n = 0; n < 2; n++) + if (vc->curr_bufs[n]) + vb2_buffer_done(&vc->curr_bufs[n]->vb.vb2_buf, + VB2_BUF_STATE_ERROR); + + spin_unlock(&vc->qlock); +} + +static struct vb2_ops tw686x_video_qops = { + .queue_setup = tw686x_queue_setup, + .buf_queue = tw686x_buf_queue, + .start_streaming = tw686x_start_streaming, + .stop_streaming = tw686x_stop_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, +}; + +static int tw686x_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct tw686x_video_channel *vc; + struct tw686x_dev *dev; + unsigned int ch; + + vc = container_of(ctrl->handler, struct tw686x_video_channel, + ctrl_handler); + dev = vc->dev; + ch = vc->ch; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + reg_write(dev, BRIGHT[ch], ctrl->val & 0xFF); + return 0; + + case V4L2_CID_CONTRAST: + reg_write(dev, CONTRAST[ch], ctrl->val); + return 0; + + case V4L2_CID_SATURATION: + reg_write(dev, SAT_U[ch], ctrl->val); + reg_write(dev, SAT_V[ch], ctrl->val); + return 0; + + case V4L2_CID_HUE: + reg_write(dev, HUE[ch], ctrl->val & 0xFF); + return 0; + } + + return -EINVAL; +} + +static const struct v4l2_ctrl_ops ctrl_ops = { + .s_ctrl = tw686x_s_ctrl, +}; + +static int tw686x_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct tw686x_video_channel *vc = video_drvdata(file); + + f->fmt.pix.width = vc->width; + f->fmt.pix.height = vc->height; + f->fmt.pix.field = vc->field; + f->fmt.pix.pixelformat = vc->format->fourcc; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + f->fmt.pix.bytesperline = f->fmt.pix.width * vc->format->depth / 8; + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + return 0; +} + +static int tw686x_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + tw686x_get_format(video_drvdata(file), f); + return 0; +} + +static int tw686x_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct tw686x_video_channel *vc = video_drvdata(file); + + tw686x_get_format(vc, f); + vc->format = format_by_fourcc(f->fmt.pix.pixelformat); + vc->field = f->fmt.pix.field; + vc->width = f->fmt.pix.width; + vc->height = f->fmt.pix.height; + return 0; +} + +static int tw686x_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct tw686x_video_channel *vc = video_drvdata(file); + struct tw686x_dev *dev = vc->dev; + + strcpy(cap->driver, "tw686x-kh"); + strcpy(cap->card, dev->name); + sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci_dev)); + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + return 0; +} + +static int tw686x_s_std(struct file *file, void *priv, v4l2_std_id id) +{ + struct tw686x_video_channel *vc = video_drvdata(file); + unsigned int cnt; + u32 sdt = 0; /* default */ + + for (cnt = 0; cnt < ARRAY_SIZE(video_standards); cnt++) + if (id & video_standards[cnt]) { + sdt = cnt; + break; + } + + reg_write(vc->dev, SDT[vc->ch], sdt); + vc->video_standard = video_standards[sdt]; + return 0; +} + +static int tw686x_g_std(struct file *file, void *priv, v4l2_std_id *id) +{ + struct tw686x_video_channel *vc = video_drvdata(file); + + *id = vc->video_standard; + return 0; +} + +static int tw686x_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + if (f->index >= ARRAY_SIZE(formats)) + return -EINVAL; + + strlcpy(f->description, formats[f->index].name, sizeof(f->description)); + f->pixelformat = formats[f->index].fourcc; + return 0; +} + +static int tw686x_g_parm(struct file *file, void *priv, + struct v4l2_streamparm *sp) +{ + struct tw686x_video_channel *vc = video_drvdata(file); + + if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + memset(&sp->parm.capture, 0, sizeof(sp->parm.capture)); + sp->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; + v4l2_video_std_frame_period(vc->video_standard, + &sp->parm.capture.timeperframe); + + return 0; +} + +static int tw686x_enum_input(struct file *file, void *priv, + struct v4l2_input *inp) +{ + /* the chip has internal multiplexer, support can be added + if the actual hw uses it */ + if (inp->index) + return -EINVAL; + + snprintf(inp->name, sizeof(inp->name), "Composite"); + inp->type = V4L2_INPUT_TYPE_CAMERA; + inp->std = V4L2_STD_ALL; + inp->capabilities = V4L2_IN_CAP_STD; + return 0; +} + +static int tw686x_g_input(struct file *file, void *priv, unsigned int *v) +{ + *v = 0; + return 0; +} + +static int tw686x_s_input(struct file *file, void *priv, unsigned int v) +{ + if (v) + return -EINVAL; + return 0; +} + +static const struct v4l2_file_operations tw686x_video_fops = { + .owner = THIS_MODULE, + .open = v4l2_fh_open, + .unlocked_ioctl = video_ioctl2, + .release = vb2_fop_release, + .poll = vb2_fop_poll, + .read = vb2_fop_read, + .mmap = vb2_fop_mmap, +}; + +static const struct v4l2_ioctl_ops tw686x_video_ioctl_ops = { + .vidioc_querycap = tw686x_querycap, + .vidioc_enum_fmt_vid_cap = tw686x_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = tw686x_g_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = tw686x_s_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = tw686x_try_fmt_vid_cap, + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + .vidioc_g_std = tw686x_g_std, + .vidioc_s_std = tw686x_s_std, + .vidioc_g_parm = tw686x_g_parm, + .vidioc_enum_input = tw686x_enum_input, + .vidioc_g_input = tw686x_g_input, + .vidioc_s_input = tw686x_s_input, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +static int video_thread(void *arg) +{ + struct tw686x_dev *dev = arg; + DECLARE_WAITQUEUE(wait, current); + + set_freezable(); + add_wait_queue(&dev->video_thread_wait, &wait); + + while (1) { + long timeout = schedule_timeout_interruptible(HZ); + unsigned int ch; + + if (timeout == -ERESTARTSYS || kthread_should_stop()) + break; + + for (ch = 0; ch < max_channels(dev); ch++) { + struct tw686x_video_channel *vc; + unsigned long flags; + u32 request, n, stat = VB2_BUF_STATE_DONE; + + vc = &dev->video_channels[ch]; + if (!(dev->video_active & (1 << ch))) + continue; + + spin_lock_irq(&dev->irq_lock); + request = dev->dma_requests & (0x01000001 << ch); + if (request) + dev->dma_requests &= ~request; + spin_unlock_irq(&dev->irq_lock); + + if (!request) + continue; + + request >>= ch; + + /* handle channel events */ + if ((request & 0x01000000) | + (reg_read(dev, VIDEO_FIFO_STATUS) & (0x01010001 << ch)) | + (reg_read(dev, VIDEO_PARSER_STATUS) & (0x00000101 << ch))) { + /* DMA Errors - reset channel */ + u32 reg; + + spin_lock_irqsave(&dev->irq_lock, flags); + reg = reg_read(dev, DMA_CMD); + /* Reset DMA channel */ + reg_write(dev, DMA_CMD, reg & ~(1 << ch)); + reg_write(dev, DMA_CMD, reg); + spin_unlock_irqrestore(&dev->irq_lock, flags); + stat = VB2_BUF_STATE_ERROR; + } + + /* handle video stream */ + mutex_lock(&vc->vb_mutex); + spin_lock(&vc->qlock); + n = !!(reg_read(dev, PB_STATUS) & (1 << ch)); + if (vc->curr_bufs[n]) { + struct vb2_v4l2_buffer *vb; + + vb = &vc->curr_bufs[n]->vb; + vb->vb2_buf.timestamp = ktime_get_ns(); + vb->field = vc->field; + if (V4L2_FIELD_HAS_BOTH(vc->field)) + vb->sequence = vc->seq++; + else + vb->sequence = (vc->seq++) / 2; + vb2_set_plane_payload(&vb->vb2_buf, 0, + vc->width * vc->height * vc->format->depth / 8); + vb2_buffer_done(&vb->vb2_buf, stat); + } + setup_descs(vc, n); + spin_unlock(&vc->qlock); + mutex_unlock(&vc->vb_mutex); + } + try_to_freeze(); + } + + remove_wait_queue(&dev->video_thread_wait, &wait); + return 0; +} + +int tw686x_kh_video_irq(struct tw686x_dev *dev) +{ + unsigned long flags, handled = 0; + u32 requests; + + spin_lock_irqsave(&dev->irq_lock, flags); + requests = dev->dma_requests; + spin_unlock_irqrestore(&dev->irq_lock, flags); + + if (requests & dev->video_active) { + wake_up_interruptible_all(&dev->video_thread_wait); + handled = 1; + } + return handled; +} + +void tw686x_kh_video_free(struct tw686x_dev *dev) +{ + unsigned int ch, n; + + if (dev->video_thread) + kthread_stop(dev->video_thread); + + for (ch = 0; ch < max_channels(dev); ch++) { + struct tw686x_video_channel *vc = &dev->video_channels[ch]; + + v4l2_ctrl_handler_free(&vc->ctrl_handler); + if (vc->device) + video_unregister_device(vc->device); + vb2_dma_sg_cleanup_ctx(vc->alloc_ctx); + for (n = 0; n < 2; n++) { + struct dma_desc *descs = &vc->sg_tables[n]; + + if (descs->virt) + pci_free_consistent(dev->pci_dev, descs->size, + descs->virt, descs->phys); + } + } + + v4l2_device_unregister(&dev->v4l2_dev); +} + +#define SG_TABLE_SIZE (MAX_SG_DESC_COUNT * sizeof(struct vdma_desc)) + +int tw686x_kh_video_init(struct tw686x_dev *dev) +{ + unsigned int ch, n; + int err; + + init_waitqueue_head(&dev->video_thread_wait); + + err = v4l2_device_register(&dev->pci_dev->dev, &dev->v4l2_dev); + if (err) + return err; + + reg_write(dev, VIDEO_CONTROL1, 0); /* NTSC, disable scaler */ + reg_write(dev, PHASE_REF, 0x00001518); /* Scatter-gather DMA mode */ + + /* setup required SG table sizes */ + for (n = 0; n < 2; n++) + if (is_second_gen(dev)) { + /* TW 6865, TW6869 - each channel needs a pair of + descriptor tables */ + for (ch = 0; ch < max_channels(dev); ch++) + dev->video_channels[ch].sg_tables[n].size = + SG_TABLE_SIZE; + + } else + /* TW 6864, TW6868 - we need to allocate a pair of + descriptor tables, common for all channels. + Each table will be bigger than 4 KB. */ + dev->video_channels[0].sg_tables[n].size = + max_channels(dev) * SG_TABLE_SIZE; + + /* allocate SG tables and initialize video channels */ + for (ch = 0; ch < max_channels(dev); ch++) { + struct tw686x_video_channel *vc = &dev->video_channels[ch]; + struct video_device *vdev; + + mutex_init(&vc->vb_mutex); + spin_lock_init(&vc->qlock); + INIT_LIST_HEAD(&vc->vidq_queued); + + vc->dev = dev; + vc->ch = ch; + + /* default settings: NTSC */ + vc->format = &formats[0]; + vc->video_standard = V4L2_STD_NTSC; + reg_write(vc->dev, SDT[vc->ch], 0); + vc->field = V4L2_FIELD_SEQ_BT; + vc->width = 704; + vc->height = 480; + + for (n = 0; n < 2; n++) { + void *cpu; + + if (vc->sg_tables[n].size) { + unsigned int reg = n ? DMA_PAGE_TABLE1_ADDR[ch] : + DMA_PAGE_TABLE0_ADDR[ch]; + + cpu = pci_alloc_consistent(dev->pci_dev, + vc->sg_tables[n].size, + &vc->sg_tables[n].phys); + if (!cpu) { + pr_err("Error allocating video DMA scatter-gather tables\n"); + err = -ENOMEM; + goto error; + } + vc->sg_tables[n].virt = cpu; + reg_write(dev, reg, vc->sg_tables[n].phys); + } else + cpu = dev->video_channels[0].sg_tables[n].virt + + ch * SG_TABLE_SIZE; + + vc->sg_descs[n] = cpu; + } + + reg_write(dev, VCTRL1[0], 0x24); + reg_write(dev, LOOP[0], 0xA5); + if (max_channels(dev) > 4) { + reg_write(dev, VCTRL1[1], 0x24); + reg_write(dev, LOOP[1], 0xA5); + } + reg_write(dev, VIDEO_FIELD_CTRL[ch], 0); + reg_write(dev, VDELAY_LO[ch], 0x14); + + vdev = video_device_alloc(); + if (!vdev) { + pr_warn("Unable to allocate video device\n"); + err = -ENOMEM; + goto error; + } + + vc->alloc_ctx = vb2_dma_sg_init_ctx(&dev->pci_dev->dev); + if (IS_ERR(vc->alloc_ctx)) { + pr_warn("Unable to initialize DMA scatter-gather context\n"); + err = PTR_ERR(vc->alloc_ctx); + goto error; + } + + vc->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + vc->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; + vc->vidq.drv_priv = vc; + vc->vidq.buf_struct_size = sizeof(struct tw686x_vb2_buf); + vc->vidq.ops = &tw686x_video_qops; + vc->vidq.mem_ops = &vb2_dma_sg_memops; + vc->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + vc->vidq.min_buffers_needed = 2; + vc->vidq.lock = &vc->vb_mutex; + vc->vidq.gfp_flags = GFP_DMA32; + + err = vb2_queue_init(&vc->vidq); + if (err) + goto error; + + strcpy(vdev->name, "TW686x-video"); + snprintf(vdev->name, sizeof(vdev->name), "%s video", dev->name); + vdev->fops = &tw686x_video_fops; + vdev->ioctl_ops = &tw686x_video_ioctl_ops; + vdev->release = video_device_release; + vdev->v4l2_dev = &dev->v4l2_dev; + vdev->queue = &vc->vidq; + vdev->tvnorms = V4L2_STD_ALL; + vdev->minor = -1; + vdev->lock = &vc->vb_mutex; + + dev->video_channels[ch].device = vdev; + video_set_drvdata(vdev, vc); + err = video_register_device(vdev, VFL_TYPE_GRABBER, -1); + if (err < 0) + goto error; + + v4l2_ctrl_handler_init(&vc->ctrl_handler, + 4 /* number of controls */); + vdev->ctrl_handler = &vc->ctrl_handler; + v4l2_ctrl_new_std(&vc->ctrl_handler, &ctrl_ops, + V4L2_CID_BRIGHTNESS, -128, 127, 1, 0); + v4l2_ctrl_new_std(&vc->ctrl_handler, &ctrl_ops, + V4L2_CID_CONTRAST, 0, 255, 1, 64); + v4l2_ctrl_new_std(&vc->ctrl_handler, &ctrl_ops, + V4L2_CID_SATURATION, 0, 255, 1, 128); + v4l2_ctrl_new_std(&vc->ctrl_handler, &ctrl_ops, V4L2_CID_HUE, + -124, 127, 1, 0); + err = vc->ctrl_handler.error; + if (err) + goto error; + + v4l2_ctrl_handler_setup(&vc->ctrl_handler); + } + + dev->video_thread = kthread_run(video_thread, dev, "tw686x_video"); + if (IS_ERR(dev->video_thread)) { + err = PTR_ERR(dev->video_thread); + goto error; + } + + return 0; + +error: + tw686x_kh_video_free(dev); + return err; +} diff --git a/drivers/staging/media/tw686x-kh/tw686x-kh.h b/drivers/staging/media/tw686x-kh/tw686x-kh.h new file mode 100644 index 0000000..dc25796 --- /dev/null +++ b/drivers/staging/media/tw686x-kh/tw686x-kh.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2015 Industrial Research Institute for Automation + * and Measurements PIAP + * + * Written by Krzysztof Ha?asa. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + */ + +#include <linux/delay.h> +#include <linux/freezer.h> +#include <linux/interrupt.h> +#include <linux/kthread.h> +#include <linux/mutex.h> +#include <linux/pci.h> +#include <media/videobuf2-dma-sg.h> +#include <linux/videodev2.h> +#include <media/v4l2-common.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-device.h> +#include <media/v4l2-ioctl.h> + +#define TYPE_MAX_CHANNELS 0x0F +#define TYPE_SECOND_GEN 0x10 + +struct tw686x_format { + char *name; + unsigned int fourcc; + unsigned int depth; + unsigned int mode; +}; + +struct dma_desc { + dma_addr_t phys; + void *virt; + unsigned int size; +}; + +struct vdma_desc { + __le32 flags_length; /* 3 MSBits for flags, 13 LSBits for length */ + __le32 phys; +}; + +struct tw686x_vb2_buf { + struct vb2_v4l2_buffer vb; + struct list_head list; +}; + +struct tw686x_video_channel { + struct tw686x_dev *dev; + + struct vb2_queue vidq; + struct list_head vidq_queued; + struct video_device *device; + struct dma_desc sg_tables[2]; + struct tw686x_vb2_buf *curr_bufs[2]; + void *alloc_ctx; + struct vdma_desc *sg_descs[2]; + + struct v4l2_ctrl_handler ctrl_handler; + const struct tw686x_format *format; + struct mutex vb_mutex; + spinlock_t qlock; + v4l2_std_id video_standard; + unsigned int width, height; + enum v4l2_field field; /* supported TOP, BOTTOM, SEQ_TB and SEQ_BT */ + unsigned int seq; /* video field or frame counter */ + unsigned int ch; +}; + +/* global device status */ +struct tw686x_dev { + spinlock_t irq_lock; + + struct v4l2_device v4l2_dev; + struct snd_card *card; /* sound card */ + + unsigned int video_active; /* active video channel mask */ + + char name[32]; + unsigned int type; + struct pci_dev *pci_dev; + __u32 __iomem *mmio; + + struct task_struct *video_thread; + wait_queue_head_t video_thread_wait; + u32 dma_requests; + + struct tw686x_video_channel video_channels[0]; +}; + +static inline uint32_t reg_read(struct tw686x_dev *dev, unsigned int reg) +{ + return readl(dev->mmio + reg); +} + +static inline void reg_write(struct tw686x_dev *dev, unsigned int reg, + uint32_t value) +{ + writel(value, dev->mmio + reg); +} + +static inline unsigned int max_channels(struct tw686x_dev *dev) +{ + return dev->type & TYPE_MAX_CHANNELS; /* 4 or 8 channels */ +} + +static inline unsigned int is_second_gen(struct tw686x_dev *dev) +{ + /* each channel has its own DMA SG table */ + return dev->type & TYPE_SECOND_GEN; +} + +int tw686x_kh_video_irq(struct tw686x_dev *dev); +int tw686x_kh_video_init(struct tw686x_dev *dev); +void tw686x_kh_video_free(struct tw686x_dev *dev); diff --git a/drivers/staging/rdma/hfi1/TODO b/drivers/staging/rdma/hfi1/TODO index 05de0da..4c6f1d7 100644 --- a/drivers/staging/rdma/hfi1/TODO +++ b/drivers/staging/rdma/hfi1/TODO @@ -3,4 +3,4 @@ July, 2015 - Remove unneeded file entries in sysfs - Remove software processing of IB protocol and place in library for use by qib, ipath (if still present), hfi1, and eventually soft-roce - +- Replace incorrect uAPI diff --git a/drivers/staging/rdma/hfi1/file_ops.c b/drivers/staging/rdma/hfi1/file_ops.c index 8396dc5..c1c5bf8 100644 --- a/drivers/staging/rdma/hfi1/file_ops.c +++ b/drivers/staging/rdma/hfi1/file_ops.c @@ -49,6 +49,8 @@ #include <linux/vmalloc.h> #include <linux/io.h> +#include <rdma/ib.h> + #include "hfi.h" #include "pio.h" #include "device.h" @@ -190,6 +192,10 @@ static ssize_t hfi1_file_write(struct file *fp, const char __user *data, int uctxt_required = 1; int must_be_root = 0; + /* FIXME: This interface cannot continue out of staging */ + if (WARN_ON_ONCE(!ib_safe_file_access(fp))) + return -EACCES; + if (count < sizeof(cmd)) { ret = -EINVAL; goto bail; @@ -791,15 +797,16 @@ static int hfi1_file_close(struct inode *inode, struct file *fp) spin_unlock_irqrestore(&dd->uctxt_lock, flags); dd->rcd[uctxt->ctxt] = NULL; + + hfi1_user_exp_rcv_free(fdata); + hfi1_clear_ctxt_pkey(dd, uctxt->ctxt); + uctxt->rcvwait_to = 0; uctxt->piowait_to = 0; uctxt->rcvnowait = 0; uctxt->pionowait = 0; uctxt->event_flags = 0; - hfi1_user_exp_rcv_free(fdata); - hfi1_clear_ctxt_pkey(dd, uctxt->ctxt); - hfi1_stats.sps_ctxts--; if (++dd->freectxts == dd->num_user_contexts) aspm_enable_all(dd); @@ -1127,27 +1134,13 @@ bail: static int user_init(struct file *fp) { - int ret; unsigned int rcvctrl_ops = 0; struct hfi1_filedata *fd = fp->private_data; struct hfi1_ctxtdata *uctxt = fd->uctxt; /* make sure that the context has already been setup */ - if (!test_bit(HFI1_CTXT_SETUP_DONE, &uctxt->event_flags)) { - ret = -EFAULT; - goto done; - } - - /* - * Subctxts don't need to initialize anything since master - * has done it. - */ - if (fd->subctxt) { - ret = wait_event_interruptible(uctxt->wait, !test_bit( - HFI1_CTXT_MASTER_UNINIT, - &uctxt->event_flags)); - goto expected; - } + if (!test_bit(HFI1_CTXT_SETUP_DONE, &uctxt->event_flags)) + return -EFAULT; /* initialize poll variables... */ uctxt->urgent = 0; @@ -1202,19 +1195,7 @@ static int user_init(struct file *fp) wake_up(&uctxt->wait); } -expected: - /* - * Expected receive has to be setup for all processes (including - * shared contexts). However, it has to be done after the master - * context has been fully configured as it depends on the - * eager/expected split of the RcvArray entries. - * Setting it up here ensures that the subcontexts will be waiting - * (due to the above wait_event_interruptible() until the master - * is setup. - */ - ret = hfi1_user_exp_rcv_init(fp); -done: - return ret; + return 0; } static int get_ctxt_info(struct file *fp, void __user *ubase, __u32 len) @@ -1261,7 +1242,7 @@ static int setup_ctxt(struct file *fp) int ret = 0; /* - * Context should be set up only once (including allocation and + * Context should be set up only once, including allocation and * programming of eager buffers. This is done if context sharing * is not requested or by the master process. */ @@ -1282,10 +1263,29 @@ static int setup_ctxt(struct file *fp) if (ret) goto done; } + } else { + ret = wait_event_interruptible(uctxt->wait, !test_bit( + HFI1_CTXT_MASTER_UNINIT, + &uctxt->event_flags)); + if (ret) + goto done; } + ret = hfi1_user_sdma_alloc_queues(uctxt, fp); if (ret) goto done; + /* + * Expected receive has to be setup for all processes (including + * shared contexts). However, it has to be done after the master + * context has been fully configured as it depends on the + * eager/expected split of the RcvArray entries. + * Setting it up here ensures that the subcontexts will be waiting + * (due to the above wait_event_interruptible() until the master + * is setup. + */ + ret = hfi1_user_exp_rcv_init(fp); + if (ret) + goto done; set_bit(HFI1_CTXT_SETUP_DONE, &uctxt->event_flags); done: @@ -1565,29 +1565,8 @@ static loff_t ui_lseek(struct file *filp, loff_t offset, int whence) { struct hfi1_devdata *dd = filp->private_data; - switch (whence) { - case SEEK_SET: - break; - case SEEK_CUR: - offset += filp->f_pos; - break; - case SEEK_END: - offset = ((dd->kregend - dd->kregbase) + DC8051_DATA_MEM_SIZE) - - offset; - break; - default: - return -EINVAL; - } - - if (offset < 0) - return -EINVAL; - - if (offset >= (dd->kregend - dd->kregbase) + DC8051_DATA_MEM_SIZE) - return -EINVAL; - - filp->f_pos = offset; - - return filp->f_pos; + return fixed_size_llseek(filp, offset, whence, + (dd->kregend - dd->kregbase) + DC8051_DATA_MEM_SIZE); } /* NOTE: assumes unsigned long is 8 bytes */ diff --git a/drivers/staging/rdma/hfi1/mmu_rb.c b/drivers/staging/rdma/hfi1/mmu_rb.c index c7ad016..b3f0682 100644 --- a/drivers/staging/rdma/hfi1/mmu_rb.c +++ b/drivers/staging/rdma/hfi1/mmu_rb.c @@ -71,6 +71,7 @@ static inline void mmu_notifier_range_start(struct mmu_notifier *, struct mm_struct *, unsigned long, unsigned long); static void mmu_notifier_mem_invalidate(struct mmu_notifier *, + struct mm_struct *, unsigned long, unsigned long); static struct mmu_rb_node *__mmu_rb_search(struct mmu_rb_handler *, unsigned long, unsigned long); @@ -137,7 +138,7 @@ void hfi1_mmu_rb_unregister(struct rb_root *root) rbnode = rb_entry(node, struct mmu_rb_node, node); rb_erase(node, root); if (handler->ops->remove) - handler->ops->remove(root, rbnode, false); + handler->ops->remove(root, rbnode, NULL); } } @@ -176,7 +177,7 @@ unlock: return ret; } -/* Caller must host handler lock */ +/* Caller must hold handler lock */ static struct mmu_rb_node *__mmu_rb_search(struct mmu_rb_handler *handler, unsigned long addr, unsigned long len) @@ -200,15 +201,21 @@ static struct mmu_rb_node *__mmu_rb_search(struct mmu_rb_handler *handler, return node; } +/* Caller must *not* hold handler lock. */ static void __mmu_rb_remove(struct mmu_rb_handler *handler, - struct mmu_rb_node *node, bool arg) + struct mmu_rb_node *node, struct mm_struct *mm) { + unsigned long flags; + /* Validity of handler and node pointers has been checked by caller. */ hfi1_cdbg(MMU, "Removing node addr 0x%llx, len %u", node->addr, node->len); + spin_lock_irqsave(&handler->lock, flags); __mmu_int_rb_remove(node, handler->root); + spin_unlock_irqrestore(&handler->lock, flags); + if (handler->ops->remove) - handler->ops->remove(handler->root, node, arg); + handler->ops->remove(handler->root, node, mm); } struct mmu_rb_node *hfi1_mmu_rb_search(struct rb_root *root, unsigned long addr, @@ -231,14 +238,11 @@ struct mmu_rb_node *hfi1_mmu_rb_search(struct rb_root *root, unsigned long addr, void hfi1_mmu_rb_remove(struct rb_root *root, struct mmu_rb_node *node) { struct mmu_rb_handler *handler = find_mmu_handler(root); - unsigned long flags; if (!handler || !node) return; - spin_lock_irqsave(&handler->lock, flags); - __mmu_rb_remove(handler, node, false); - spin_unlock_irqrestore(&handler->lock, flags); + __mmu_rb_remove(handler, node, NULL); } static struct mmu_rb_handler *find_mmu_handler(struct rb_root *root) @@ -260,7 +264,7 @@ unlock: static inline void mmu_notifier_page(struct mmu_notifier *mn, struct mm_struct *mm, unsigned long addr) { - mmu_notifier_mem_invalidate(mn, addr, addr + PAGE_SIZE); + mmu_notifier_mem_invalidate(mn, mm, addr, addr + PAGE_SIZE); } static inline void mmu_notifier_range_start(struct mmu_notifier *mn, @@ -268,25 +272,31 @@ static inline void mmu_notifier_range_start(struct mmu_notifier *mn, unsigned long start, unsigned long end) { - mmu_notifier_mem_invalidate(mn, start, end); + mmu_notifier_mem_invalidate(mn, mm, start, end); } static void mmu_notifier_mem_invalidate(struct mmu_notifier *mn, + struct mm_struct *mm, unsigned long start, unsigned long end) { struct mmu_rb_handler *handler = container_of(mn, struct mmu_rb_handler, mn); struct rb_root *root = handler->root; - struct mmu_rb_node *node; + struct mmu_rb_node *node, *ptr = NULL; unsigned long flags; spin_lock_irqsave(&handler->lock, flags); - for (node = __mmu_int_rb_iter_first(root, start, end - 1); node; - node = __mmu_int_rb_iter_next(node, start, end - 1)) { + for (node = __mmu_int_rb_iter_first(root, start, end - 1); + node; node = ptr) { + /* Guard against node removal. */ + ptr = __mmu_int_rb_iter_next(node, start, end - 1); hfi1_cdbg(MMU, "Invalidating node addr 0x%llx, len %u", node->addr, node->len); - if (handler->ops->invalidate(root, node)) - __mmu_rb_remove(handler, node, true); + if (handler->ops->invalidate(root, node)) { + spin_unlock_irqrestore(&handler->lock, flags); + __mmu_rb_remove(handler, node, mm); + spin_lock_irqsave(&handler->lock, flags); + } } spin_unlock_irqrestore(&handler->lock, flags); } diff --git a/drivers/staging/rdma/hfi1/mmu_rb.h b/drivers/staging/rdma/hfi1/mmu_rb.h index f8523fd..19a306e 100644 --- a/drivers/staging/rdma/hfi1/mmu_rb.h +++ b/drivers/staging/rdma/hfi1/mmu_rb.h @@ -59,7 +59,8 @@ struct mmu_rb_node { struct mmu_rb_ops { bool (*filter)(struct mmu_rb_node *, unsigned long, unsigned long); int (*insert)(struct rb_root *, struct mmu_rb_node *); - void (*remove)(struct rb_root *, struct mmu_rb_node *, bool); + void (*remove)(struct rb_root *, struct mmu_rb_node *, + struct mm_struct *); int (*invalidate)(struct rb_root *, struct mmu_rb_node *); }; diff --git a/drivers/staging/rdma/hfi1/qp.c b/drivers/staging/rdma/hfi1/qp.c index 29a5ad2..dc9119e 100644 --- a/drivers/staging/rdma/hfi1/qp.c +++ b/drivers/staging/rdma/hfi1/qp.c @@ -519,10 +519,12 @@ static void iowait_sdma_drained(struct iowait *wait) * do the flush work until that QP's * sdma work has finished. */ + spin_lock(&qp->s_lock); if (qp->s_flags & RVT_S_WAIT_DMA) { qp->s_flags &= ~RVT_S_WAIT_DMA; hfi1_schedule_send(qp); } + spin_unlock(&qp->s_lock); } /** diff --git a/drivers/staging/rdma/hfi1/user_exp_rcv.c b/drivers/staging/rdma/hfi1/user_exp_rcv.c index 0861e09..8bd56d5 100644 --- a/drivers/staging/rdma/hfi1/user_exp_rcv.c +++ b/drivers/staging/rdma/hfi1/user_exp_rcv.c @@ -87,7 +87,8 @@ static u32 find_phys_blocks(struct page **, unsigned, struct tid_pageset *); static int set_rcvarray_entry(struct file *, unsigned long, u32, struct tid_group *, struct page **, unsigned); static int mmu_rb_insert(struct rb_root *, struct mmu_rb_node *); -static void mmu_rb_remove(struct rb_root *, struct mmu_rb_node *, bool); +static void mmu_rb_remove(struct rb_root *, struct mmu_rb_node *, + struct mm_struct *); static int mmu_rb_invalidate(struct rb_root *, struct mmu_rb_node *); static int program_rcvarray(struct file *, unsigned long, struct tid_group *, struct tid_pageset *, unsigned, u16, struct page **, @@ -254,6 +255,8 @@ int hfi1_user_exp_rcv_free(struct hfi1_filedata *fd) struct hfi1_ctxtdata *uctxt = fd->uctxt; struct tid_group *grp, *gptr; + if (!test_bit(HFI1_CTXT_SETUP_DONE, &uctxt->event_flags)) + return 0; /* * The notifier would have been removed when the process'es mm * was freed. @@ -899,7 +902,7 @@ static int unprogram_rcvarray(struct file *fp, u32 tidinfo, if (!node || node->rcventry != (uctxt->expected_base + rcventry)) return -EBADF; if (HFI1_CAP_IS_USET(TID_UNMAP)) - mmu_rb_remove(&fd->tid_rb_root, &node->mmu, false); + mmu_rb_remove(&fd->tid_rb_root, &node->mmu, NULL); else hfi1_mmu_rb_remove(&fd->tid_rb_root, &node->mmu); @@ -965,7 +968,7 @@ static void unlock_exp_tids(struct hfi1_ctxtdata *uctxt, continue; if (HFI1_CAP_IS_USET(TID_UNMAP)) mmu_rb_remove(&fd->tid_rb_root, - &node->mmu, false); + &node->mmu, NULL); else hfi1_mmu_rb_remove(&fd->tid_rb_root, &node->mmu); @@ -1032,7 +1035,7 @@ static int mmu_rb_insert(struct rb_root *root, struct mmu_rb_node *node) } static void mmu_rb_remove(struct rb_root *root, struct mmu_rb_node *node, - bool notifier) + struct mm_struct *mm) { struct hfi1_filedata *fdata = container_of(root, struct hfi1_filedata, tid_rb_root); diff --git a/drivers/staging/rdma/hfi1/user_sdma.c b/drivers/staging/rdma/hfi1/user_sdma.c index ab6b6a4..d53a659 100644 --- a/drivers/staging/rdma/hfi1/user_sdma.c +++ b/drivers/staging/rdma/hfi1/user_sdma.c @@ -278,7 +278,8 @@ static inline void pq_update(struct hfi1_user_sdma_pkt_q *); static void user_sdma_free_request(struct user_sdma_request *, bool); static int pin_vector_pages(struct user_sdma_request *, struct user_sdma_iovec *); -static void unpin_vector_pages(struct mm_struct *, struct page **, unsigned); +static void unpin_vector_pages(struct mm_struct *, struct page **, unsigned, + unsigned); static int check_header_template(struct user_sdma_request *, struct hfi1_pkt_header *, u32, u32); static int set_txreq_header(struct user_sdma_request *, @@ -299,7 +300,8 @@ static int defer_packet_queue( static void activate_packet_queue(struct iowait *, int); static bool sdma_rb_filter(struct mmu_rb_node *, unsigned long, unsigned long); static int sdma_rb_insert(struct rb_root *, struct mmu_rb_node *); -static void sdma_rb_remove(struct rb_root *, struct mmu_rb_node *, bool); +static void sdma_rb_remove(struct rb_root *, struct mmu_rb_node *, + struct mm_struct *); static int sdma_rb_invalidate(struct rb_root *, struct mmu_rb_node *); static struct mmu_rb_ops sdma_rb_ops = { @@ -1063,8 +1065,10 @@ static int pin_vector_pages(struct user_sdma_request *req, rb_node = hfi1_mmu_rb_search(&pq->sdma_rb_root, (unsigned long)iovec->iov.iov_base, iovec->iov.iov_len); - if (rb_node) + if (rb_node && !IS_ERR(rb_node)) node = container_of(rb_node, struct sdma_mmu_node, rb); + else + rb_node = NULL; if (!node) { node = kzalloc(sizeof(*node), GFP_KERNEL); @@ -1107,7 +1111,8 @@ retry: goto bail; } if (pinned != npages) { - unpin_vector_pages(current->mm, pages, pinned); + unpin_vector_pages(current->mm, pages, node->npages, + pinned); ret = -EFAULT; goto bail; } @@ -1147,9 +1152,9 @@ bail: } static void unpin_vector_pages(struct mm_struct *mm, struct page **pages, - unsigned npages) + unsigned start, unsigned npages) { - hfi1_release_user_pages(mm, pages, npages, 0); + hfi1_release_user_pages(mm, pages + start, npages, 0); kfree(pages); } @@ -1502,7 +1507,7 @@ static void user_sdma_free_request(struct user_sdma_request *req, bool unpin) &req->pq->sdma_rb_root, (unsigned long)req->iovs[i].iov.iov_base, req->iovs[i].iov.iov_len); - if (!mnode) + if (!mnode || IS_ERR(mnode)) continue; node = container_of(mnode, struct sdma_mmu_node, rb); @@ -1547,7 +1552,7 @@ static int sdma_rb_insert(struct rb_root *root, struct mmu_rb_node *mnode) } static void sdma_rb_remove(struct rb_root *root, struct mmu_rb_node *mnode, - bool notifier) + struct mm_struct *mm) { struct sdma_mmu_node *node = container_of(mnode, struct sdma_mmu_node, rb); @@ -1557,14 +1562,20 @@ static void sdma_rb_remove(struct rb_root *root, struct mmu_rb_node *mnode, node->pq->n_locked -= node->npages; spin_unlock(&node->pq->evict_lock); - unpin_vector_pages(notifier ? NULL : current->mm, node->pages, + /* + * If mm is set, we are being called by the MMU notifier and we + * should not pass a mm_struct to unpin_vector_page(). This is to + * prevent a deadlock when hfi1_release_user_pages() attempts to + * take the mmap_sem, which the MMU notifier has already taken. + */ + unpin_vector_pages(mm ? NULL : current->mm, node->pages, 0, node->npages); /* * If called by the MMU notifier, we have to adjust the pinned * page count ourselves. */ - if (notifier) - current->mm->pinned_vm -= node->npages; + if (mm) + mm->pinned_vm -= node->npages; kfree(node); } diff --git a/drivers/staging/rtl8188eu/os_dep/mon.c b/drivers/staging/rtl8188eu/os_dep/mon.c index 63bb875..d976e5e 100644 --- a/drivers/staging/rtl8188eu/os_dep/mon.c +++ b/drivers/staging/rtl8188eu/os_dep/mon.c @@ -155,7 +155,7 @@ static void mon_setup(struct net_device *dev) dev->netdev_ops = &mon_netdev_ops; dev->destructor = free_netdev; ether_setup(dev); - dev->tx_queue_len = 0; + dev->priv_flags |= IFF_NO_QUEUE; dev->type = ARPHRD_IEEE80211; /* * Use a locally administered address (IEEE 802) diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index 9b7cc7d..13a5ddc 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c @@ -1792,7 +1792,7 @@ static short _rtl92e_tx(struct net_device *dev, struct sk_buff *skb) __skb_queue_tail(&ring->queue, skb); pdesc->OWN = 1; spin_unlock_irqrestore(&priv->irq_th_lock, flags); - dev->trans_start = jiffies; + netif_trans_update(dev); rtl92e_writew(dev, TPPoll, 0x01 << tcb_desc->queue_index); return 0; diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c index cfab715..62154e3 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac.c +++ b/drivers/staging/rtl8192e/rtllib_softmac.c @@ -1991,7 +1991,7 @@ static short rtllib_sta_ps_sleep(struct rtllib_device *ieee, u64 *time) return 2; if (!time_after(jiffies, - ieee->dev->trans_start + msecs_to_jiffies(timeout))) + dev_trans_start(ieee->dev) + msecs_to_jiffies(timeout))) return 0; if (!time_after(jiffies, ieee->last_rx_ps_time + msecs_to_jiffies(timeout))) diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c index ae1274c..d705595 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c @@ -249,7 +249,7 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee ieee->seq_ctrl[0]++; /* avoid watchdog triggers */ - ieee->dev->trans_start = jiffies; + netif_trans_update(ieee->dev); ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate); //dev_kfree_skb_any(skb);//edit by thomas } @@ -302,7 +302,7 @@ inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *i ieee->seq_ctrl[0]++; /* avoid watchdog triggers */ - ieee->dev->trans_start = jiffies; + netif_trans_update(ieee->dev); ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate); }else{ @@ -1737,7 +1737,7 @@ static short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, return 2; if(!time_after(jiffies, - ieee->dev->trans_start + msecs_to_jiffies(timeout))) + dev_trans_start(ieee->dev) + msecs_to_jiffies(timeout))) return 0; if(!time_after(jiffies, @@ -2205,7 +2205,7 @@ static void ieee80211_resume_tx(struct ieee80211_device *ieee) ieee->dev, ieee->rate); //(i+1)<ieee->tx_pending.txb->nr_frags); ieee->stats.tx_packets++; - ieee->dev->trans_start = jiffies; + netif_trans_update(ieee->dev); } } diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index 849a95e..4af0140 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -1108,7 +1108,7 @@ static void rtl8192_tx_isr(struct urb *tx_urb) if (tcb_desc->queue_index != TXCMD_QUEUE) { if (tx_urb->status == 0) { - dev->trans_start = jiffies; + netif_trans_update(dev); priv->stats.txoktotal++; priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++; priv->stats.txbytesunicast += @@ -1715,7 +1715,7 @@ short rtl8192_tx(struct net_device *dev, struct sk_buff *skb) return -1; } } - dev->trans_start = jiffies; + netif_trans_update(dev); atomic_inc(&priv->tx_pending[tcb_desc->queue_index]); return 0; } diff --git a/drivers/staging/rtl8723au/core/rtw_mlme_ext.c b/drivers/staging/rtl8723au/core/rtw_mlme_ext.c index f4fff38..7dd1540 100644 --- a/drivers/staging/rtl8723au/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8723au/core/rtw_mlme_ext.c @@ -2113,10 +2113,10 @@ static int on_action_public23a(struct rtw_adapter *padapter, if (channel <= RTW_CH_MAX_2G_CHANNEL) freq = ieee80211_channel_to_frequency(channel, - IEEE80211_BAND_2GHZ); + NL80211_BAND_2GHZ); else freq = ieee80211_channel_to_frequency(channel, - IEEE80211_BAND_5GHZ); + NL80211_BAND_5GHZ); if (cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pframe, skb->len, 0)) diff --git a/drivers/staging/rtl8723au/include/ieee80211.h b/drivers/staging/rtl8723au/include/ieee80211.h index 3aa40a3..634102e 100644 --- a/drivers/staging/rtl8723au/include/ieee80211.h +++ b/drivers/staging/rtl8723au/include/ieee80211.h @@ -266,7 +266,7 @@ join_res: /* Represent channel details, subset of ieee80211_channel */ struct rtw_ieee80211_channel { - /* enum ieee80211_band band; */ + /* enum nl80211_band band; */ /* u16 center_freq; */ u16 hw_value; u32 flags; diff --git a/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c index 12d1844..0da559d 100644 --- a/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c @@ -39,7 +39,7 @@ static const u32 rtw_cipher_suites[] = { } #define CHAN2G(_channel, _freq, _flags) { \ - .band = IEEE80211_BAND_2GHZ, \ + .band = NL80211_BAND_2GHZ, \ .center_freq = (_freq), \ .hw_value = (_channel), \ .flags = (_flags), \ @@ -48,7 +48,7 @@ static const u32 rtw_cipher_suites[] = { } #define CHAN5G(_channel, _flags) { \ - .band = IEEE80211_BAND_5GHZ, \ + .band = NL80211_BAND_5GHZ, \ .center_freq = 5000 + (5 * (_channel)), \ .hw_value = (_channel), \ .flags = (_flags), \ @@ -143,15 +143,15 @@ static void rtw_5g_rates_init(struct ieee80211_rate *rates) } static struct ieee80211_supported_band * -rtw_spt_band_alloc(enum ieee80211_band band) +rtw_spt_band_alloc(enum nl80211_band band) { struct ieee80211_supported_band *spt_band = NULL; int n_channels, n_bitrates; - if (band == IEEE80211_BAND_2GHZ) { + if (band == NL80211_BAND_2GHZ) { n_channels = RTW_2G_CHANNELS_NUM; n_bitrates = RTW_G_RATES_NUM; - } else if (band == IEEE80211_BAND_5GHZ) { + } else if (band == NL80211_BAND_5GHZ) { n_channels = RTW_5G_CHANNELS_NUM; n_bitrates = RTW_A_RATES_NUM; } else { @@ -176,10 +176,10 @@ rtw_spt_band_alloc(enum ieee80211_band band) spt_band->n_channels = n_channels; spt_band->n_bitrates = n_bitrates; - if (band == IEEE80211_BAND_2GHZ) { + if (band == NL80211_BAND_2GHZ) { rtw_2g_channels_init(spt_band->channels); rtw_2g_rates_init(spt_band->bitrates); - } else if (band == IEEE80211_BAND_5GHZ) { + } else if (band == NL80211_BAND_5GHZ) { rtw_5g_channels_init(spt_band->channels); rtw_5g_rates_init(spt_band->bitrates); } @@ -257,10 +257,10 @@ static int rtw_cfg80211_inform_bss(struct rtw_adapter *padapter, channel = pnetwork->network.DSConfig; if (channel <= RTW_CH_MAX_2G_CHANNEL) freq = ieee80211_channel_to_frequency(channel, - IEEE80211_BAND_2GHZ); + NL80211_BAND_2GHZ); else freq = ieee80211_channel_to_frequency(channel, - IEEE80211_BAND_5GHZ); + NL80211_BAND_5GHZ); notify_channel = ieee80211_get_channel(wiphy, freq); @@ -322,11 +322,11 @@ void rtw_cfg80211_indicate_connect(struct rtw_adapter *padapter) if (channel <= RTW_CH_MAX_2G_CHANNEL) freq = ieee80211_channel_to_frequency(channel, - IEEE80211_BAND_2GHZ); + NL80211_BAND_2GHZ); else freq = ieee80211_channel_to_frequency(channel, - IEEE80211_BAND_5GHZ); + NL80211_BAND_5GHZ); notify_channel = ieee80211_get_channel(wiphy, freq); @@ -2360,10 +2360,10 @@ void rtw_cfg80211_indicate_sta_assoc(struct rtw_adapter *padapter, channel = pmlmeext->cur_channel; if (channel <= RTW_CH_MAX_2G_CHANNEL) freq = ieee80211_channel_to_frequency(channel, - IEEE80211_BAND_2GHZ); + NL80211_BAND_2GHZ); else freq = ieee80211_channel_to_frequency(channel, - IEEE80211_BAND_5GHZ); + NL80211_BAND_5GHZ); cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pmgmt_frame, frame_len, 0); @@ -2392,10 +2392,10 @@ void rtw_cfg80211_indicate_sta_disassoc(struct rtw_adapter *padapter, channel = pmlmeext->cur_channel; if (channel <= RTW_CH_MAX_2G_CHANNEL) freq = ieee80211_channel_to_frequency(channel, - IEEE80211_BAND_2GHZ); + NL80211_BAND_2GHZ); else freq = ieee80211_channel_to_frequency(channel, - IEEE80211_BAND_5GHZ); + NL80211_BAND_5GHZ); mgmt.frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH); @@ -3109,7 +3109,7 @@ static struct cfg80211_ops rtw_cfg80211_ops = { }; static void rtw_cfg80211_init_ht_capab(struct ieee80211_sta_ht_cap *ht_cap, - enum ieee80211_band band, u8 rf_type) + enum nl80211_band band, u8 rf_type) { #define MAX_BIT_RATE_40MHZ_MCS15 300 /* Mbps */ @@ -3133,7 +3133,7 @@ static void rtw_cfg80211_init_ht_capab(struct ieee80211_sta_ht_cap *ht_cap, ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; /* - *hw->wiphy->bands[IEEE80211_BAND_2GHZ] + *hw->wiphy->bands[NL80211_BAND_2GHZ] *base on ant_num *rx_mask: RX mask *if rx_ant = 1 rx_mask[0]= 0xff;==>MCS0-MCS7 @@ -3173,19 +3173,19 @@ void rtw_cfg80211_init_wiphy(struct rtw_adapter *padapter) /* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */ { - bands = wiphy->bands[IEEE80211_BAND_2GHZ]; + bands = wiphy->bands[NL80211_BAND_2GHZ]; if (bands) rtw_cfg80211_init_ht_capab(&bands->ht_cap, - IEEE80211_BAND_2GHZ, + NL80211_BAND_2GHZ, rf_type); } /* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */ { - bands = wiphy->bands[IEEE80211_BAND_5GHZ]; + bands = wiphy->bands[NL80211_BAND_5GHZ]; if (bands) rtw_cfg80211_init_ht_capab(&bands->ht_cap, - IEEE80211_BAND_5GHZ, + NL80211_BAND_5GHZ, rf_type); } } @@ -3224,11 +3224,11 @@ static void rtw_cfg80211_preinit_wiphy(struct rtw_adapter *padapter, wiphy->n_cipher_suites = ARRAY_SIZE(rtw_cipher_suites); /* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */ - wiphy->bands[IEEE80211_BAND_2GHZ] = - rtw_spt_band_alloc(IEEE80211_BAND_2GHZ); + wiphy->bands[NL80211_BAND_2GHZ] = + rtw_spt_band_alloc(NL80211_BAND_2GHZ); /* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */ - wiphy->bands[IEEE80211_BAND_5GHZ] = - rtw_spt_band_alloc(IEEE80211_BAND_5GHZ); + wiphy->bands[NL80211_BAND_5GHZ] = + rtw_spt_band_alloc(NL80211_BAND_5GHZ); wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; wiphy->flags |= WIPHY_FLAG_OFFCHAN_TX | WIPHY_FLAG_HAVE_AP_SME; @@ -3313,8 +3313,8 @@ void rtw_wdev_free(struct wireless_dev *wdev) if (!wdev) return; - kfree(wdev->wiphy->bands[IEEE80211_BAND_2GHZ]); - kfree(wdev->wiphy->bands[IEEE80211_BAND_5GHZ]); + kfree(wdev->wiphy->bands[NL80211_BAND_2GHZ]); + kfree(wdev->wiphy->bands[NL80211_BAND_5GHZ]); wiphy_free(wdev->wiphy); diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 5fbda7b..9cf4f84 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -2425,7 +2425,7 @@ static __init uint32_t visorutil_spar_detect(void) { unsigned int eax, ebx, ecx, edx; - if (cpu_has_hypervisor) { + if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) { /* check the ID */ cpuid(UNISYS_SPAR_LEAF_ID, &eax, &ebx, &ecx, &edx); return (ebx == UNISYS_SPAR_ID_EBX) && diff --git a/drivers/staging/vme/devices/vme_pio2_gpio.c b/drivers/staging/vme/devices/vme_pio2_gpio.c index df992c3..6d361201 100644 --- a/drivers/staging/vme/devices/vme_pio2_gpio.c +++ b/drivers/staging/vme/devices/vme_pio2_gpio.c @@ -17,7 +17,7 @@ #include <linux/device.h> #include <linux/platform_device.h> #include <linux/ctype.h> -#include <linux/gpio.h> +#include <linux/gpio/driver.h> #include <linux/slab.h> #include <linux/vme.h> @@ -25,16 +25,11 @@ static const char driver_name[] = "pio2_gpio"; -static struct pio2_card *gpio_to_pio2_card(struct gpio_chip *chip) -{ - return container_of(chip, struct pio2_card, gc); -} - static int pio2_gpio_get(struct gpio_chip *chip, unsigned int offset) { u8 reg; int retval; - struct pio2_card *card = gpio_to_pio2_card(chip); + struct pio2_card *card = gpiochip_get_data(chip); if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == OUTPUT) | (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) { @@ -71,7 +66,7 @@ static void pio2_gpio_set(struct gpio_chip *chip, { u8 reg; int retval; - struct pio2_card *card = gpio_to_pio2_card(chip); + struct pio2_card *card = gpiochip_get_data(chip); if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == INPUT) | (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) { @@ -100,7 +95,7 @@ static void pio2_gpio_set(struct gpio_chip *chip, static int pio2_gpio_dir_in(struct gpio_chip *chip, unsigned offset) { int data; - struct pio2_card *card = gpio_to_pio2_card(chip); + struct pio2_card *card = gpiochip_get_data(chip); if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == OUTPUT) | (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) { @@ -119,7 +114,7 @@ static int pio2_gpio_dir_in(struct gpio_chip *chip, unsigned offset) static int pio2_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value) { int data; - struct pio2_card *card = gpio_to_pio2_card(chip); + struct pio2_card *card = gpiochip_get_data(chip); if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == INPUT) | (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) { @@ -205,7 +200,7 @@ int pio2_gpio_init(struct pio2_card *card) card->gc.set = pio2_gpio_set; /* This function adds a memory mapped GPIO chip */ - retval = gpiochip_add(&card->gc); + retval = gpiochip_add_data(&card->gc, card); if (retval) { dev_err(&card->vdev->dev, "Unable to register GPIO\n"); kfree(card->gc.label); diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c index 9ac1ef9..b7d43a5 100644 --- a/drivers/staging/vt6655/channel.c +++ b/drivers/staging/vt6655/channel.c @@ -144,7 +144,7 @@ void vnt_init_bands(struct vnt_private *priv) ch[i].flags = IEEE80211_CHAN_NO_HT40; } - priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = + priv->hw->wiphy->bands[NL80211_BAND_5GHZ] = &vnt_supported_5ghz_band; /* fallthrough */ case RF_RFMD2959: @@ -159,7 +159,7 @@ void vnt_init_bands(struct vnt_private *priv) ch[i].flags = IEEE80211_CHAN_NO_HT40; } - priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = + priv->hw->wiphy->bands[NL80211_BAND_2GHZ] = &vnt_supported_2ghz_band; break; } diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index c3eea07..4941640 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -812,7 +812,7 @@ static int vnt_int_report_rate(struct vnt_private *priv, else if (fb_option & FIFOCTL_AUTO_FB_1) tx_rate = fallback_rate1[tx_rate][retry]; - if (info->band == IEEE80211_BAND_5GHZ) + if (info->band == NL80211_BAND_5GHZ) idx = tx_rate - RATE_6M; else idx = tx_rate; @@ -1290,7 +1290,7 @@ static int vnt_config(struct ieee80211_hw *hw, u32 changed) (conf->flags & IEEE80211_CONF_OFFCHANNEL)) { set_channel(priv, conf->chandef.chan); - if (conf->chandef.chan->band == IEEE80211_BAND_5GHZ) + if (conf->chandef.chan->band == NL80211_BAND_5GHZ) bb_type = BB_TYPE_11A; else bb_type = BB_TYPE_11G; diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c index 1a2dda0..e4c3165 100644 --- a/drivers/staging/vt6655/rxtx.c +++ b/drivers/staging/vt6655/rxtx.c @@ -1307,7 +1307,7 @@ int vnt_generate_fifo_header(struct vnt_private *priv, u32 dma_idx, } if (current_rate > RATE_11M) { - if (info->band == IEEE80211_BAND_5GHZ) { + if (info->band == NL80211_BAND_5GHZ) { pkt_type = PK_TYPE_11A; } else { if (tx_rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT) diff --git a/drivers/staging/vt6656/channel.c b/drivers/staging/vt6656/channel.c index a0fe288..a4299f4 100644 --- a/drivers/staging/vt6656/channel.c +++ b/drivers/staging/vt6656/channel.c @@ -153,7 +153,7 @@ void vnt_init_bands(struct vnt_private *priv) ch[i].flags = IEEE80211_CHAN_NO_HT40; } - priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = + priv->hw->wiphy->bands[NL80211_BAND_5GHZ] = &vnt_supported_5ghz_band; /* fallthrough */ case RF_AL2230: @@ -167,7 +167,7 @@ void vnt_init_bands(struct vnt_private *priv) ch[i].flags = IEEE80211_CHAN_NO_HT40; } - priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = + priv->hw->wiphy->bands[NL80211_BAND_2GHZ] = &vnt_supported_2ghz_band; break; } diff --git a/drivers/staging/vt6656/int.c b/drivers/staging/vt6656/int.c index 8d05acb..73538fb 100644 --- a/drivers/staging/vt6656/int.c +++ b/drivers/staging/vt6656/int.c @@ -97,7 +97,7 @@ static int vnt_int_report_rate(struct vnt_private *priv, u8 pkt_no, u8 tsr) else if (context->fb_option == AUTO_FB_1) tx_rate = fallback_rate1[tx_rate][retry]; - if (info->band == IEEE80211_BAND_5GHZ) + if (info->band == NL80211_BAND_5GHZ) idx = tx_rate - RATE_6M; else idx = tx_rate; diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index f9afab7..fc5fe4e 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -662,7 +662,7 @@ static int vnt_config(struct ieee80211_hw *hw, u32 changed) (conf->flags & IEEE80211_CONF_OFFCHANNEL)) { vnt_set_channel(priv, conf->chandef.chan->hw_value); - if (conf->chandef.chan->band == IEEE80211_BAND_5GHZ) + if (conf->chandef.chan->band == NL80211_BAND_5GHZ) bb_type = BB_TYPE_11A; else bb_type = BB_TYPE_11G; diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index b74e320..aa59e7f 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -813,7 +813,7 @@ int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb) } if (current_rate > RATE_11M) { - if (info->band == IEEE80211_BAND_5GHZ) { + if (info->band == NL80211_BAND_5GHZ) { pkt_type = PK_TYPE_11A; } else { if (tx_rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT) diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 448a5c8..544917d 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -102,7 +102,7 @@ static u8 op_ifcs; u8 wilc_initialized = 1; #define CHAN2G(_channel, _freq, _flags) { \ - .band = IEEE80211_BAND_2GHZ, \ + .band = NL80211_BAND_2GHZ, \ .center_freq = (_freq), \ .hw_value = (_channel), \ .flags = (_flags), \ @@ -241,7 +241,7 @@ static void refresh_scan(void *user_void, u8 all, bool direct_scan) struct ieee80211_channel *channel; if (network_info) { - freq = ieee80211_channel_to_frequency((s32)network_info->ch, IEEE80211_BAND_2GHZ); + freq = ieee80211_channel_to_frequency((s32)network_info->ch, NL80211_BAND_2GHZ); channel = ieee80211_get_channel(wiphy, freq); rssi = get_rssi_avg(network_info); @@ -409,7 +409,7 @@ static void CfgScanResult(enum scan_event scan_event, return; if (network_info) { - s32Freq = ieee80211_channel_to_frequency((s32)network_info->ch, IEEE80211_BAND_2GHZ); + s32Freq = ieee80211_channel_to_frequency((s32)network_info->ch, NL80211_BAND_2GHZ); channel = ieee80211_get_channel(wiphy, s32Freq); if (!channel) @@ -1451,7 +1451,7 @@ void WILC_WFI_p2p_rx(struct net_device *dev, u8 *buff, u32 size) return; } } else { - s32Freq = ieee80211_channel_to_frequency(curr_channel, IEEE80211_BAND_2GHZ); + s32Freq = ieee80211_channel_to_frequency(curr_channel, NL80211_BAND_2GHZ); if (ieee80211_is_action(buff[FRAME_TYPE_ID])) { if (priv->bCfgScanning && time_after_eq(jiffies, (unsigned long)pstrWFIDrv->p2p_timeout)) { @@ -2246,7 +2246,7 @@ static struct wireless_dev *WILC_WFI_CfgAlloc(void) WILC_WFI_band_2ghz.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K; WILC_WFI_band_2ghz.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE; - wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &WILC_WFI_band_2ghz; + wdev->wiphy->bands[NL80211_BAND_2GHZ] = &WILC_WFI_band_2ghz; return wdev; diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 8bad018..2438cf7 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -415,7 +415,7 @@ static int prism2_scan(struct wiphy *wiphy, ie_len = ie_buf[1] + 2; memcpy(&ie_buf[2], &(msg2.ssid.data.data), msg2.ssid.data.len); freq = ieee80211_channel_to_frequency(msg2.dschannel.data, - IEEE80211_BAND_2GHZ); + NL80211_BAND_2GHZ); bss = cfg80211_inform_bss(wiphy, ieee80211_get_channel(wiphy, freq), CFG80211_BSS_FTYPE_UNKNOWN, @@ -758,9 +758,9 @@ static struct wiphy *wlan_create_wiphy(struct device *dev, wlandevice_t *wlandev priv->band.n_channels = ARRAY_SIZE(prism2_channels); priv->band.bitrates = priv->rates; priv->band.n_bitrates = ARRAY_SIZE(prism2_rates); - priv->band.band = IEEE80211_BAND_2GHZ; + priv->band.band = NL80211_BAND_2GHZ; priv->band.ht_cap.ht_supported = false; - wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; + wiphy->bands[NL80211_BAND_2GHZ] = &priv->band; set_wiphy_dev(wiphy, dev); wiphy->privid = prism2_wiphy_privid; diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index 88255ce..1f9dfba 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -393,7 +393,7 @@ static int p80211knetdev_hard_start_xmit(struct sk_buff *skb, goto failed; } - netdev->trans_start = jiffies; + netif_trans_update(netdev); netdev->stats.tx_packets++; /* count only the packet payload */ |