Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d022bafb authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6: (43 commits)
  staging: slicoss: update README
  otus/zdusb.c: additional USB idnetifier
  Staging: go7007: fix build issues
  Staging: sxg: Fix leaks and checksum errors in transmit code path
  Staging: sxg: Fix sleep in atomic context warning while loading driver
  Staging: sxg: Use correct queue_id for transmitting non-TCP packets
  Staging: sxg: Fire watchdog timer at end of open routine to change the link
  Staging: Pohmelfs: Add load balancing between network states with the same priority.
  Staging: Pohmelfs: Added IO permissions and priorities.
  Staging: Pohmelfs: Added ->show_stats() callback.
  Staging: Pohmelfs: Drop ftrans debugging code.
  Staging: Pohmelfs: Use wait_on_page_timeout when waiting for remote directory sync instead of hardcoded 25 seconds.
  Staging: Pohmelfs: Reduce debugging noise about non-existing objects.
  Staging: Pohmelfs: Sync fs before killing it, since dentry cache is shrunk before writeback is invoked via generic_shutdown_super()
  Staging: Pohmelfs: Extend remount option.
  Staging: Pohmelfs: Set NETFS_INODE_REMOTE_SYNCED and clear NETFS_INODE_OWNED bits in the root inode.
  Staging: Pohmelfs: Added 'need_lock' variable into debug print.
  Staging: Pohmelfs: Disable read lock in pohmelfs_getattr().
  Staging: Pohmelfs: Move parent lock to the place where we really have to send a lookup request to the server.
  Staging: pohmelfs: Populate dentry cache when receiving the new readdir entry.
  ...
parents 74a205a3 1a92e82a
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -56,9 +56,10 @@ workloads and can fully utilize the bandwidth to the servers when doing bulk
data transfers.

POHMELFS clients operate with a working set of servers and are capable of balancing read-only
operations (like lookups or directory listings) between them.
operations (like lookups or directory listings) between them according to IO priorities.
Administrators can add or remove servers from the set at run-time via special commands (described
in Documentation/pohmelfs/info.txt file). Writes are replicated to all servers.
in Documentation/pohmelfs/info.txt file). Writes are replicated to all servers, which are connected
with write permission turned on. IO priority and permissions can be changed in run-time.

POHMELFS is capable of full data channel encryption and/or strong crypto hashing.
One can select any kernel supported cipher, encryption mode, hash type and operation mode
+17 −4
Original line number Diff line number Diff line
POHMELFS usage information.

Mount options:
Mount options.
All but index, number of crypto threads and maximum IO size can changed via remount.

idx=%u
 Each mountpoint is associated with a special index via this option.
 Administrator can add or remove servers from the given index, so all mounts,
@@ -52,16 +54,27 @@ mcache_timeout=%u

Usage examples.

Add (or remove if it already exists) server server1.net:1025 into the working set with index $idx
Add server server1.net:1025 into the working set with index $idx
with appropriate hash algorithm and key file and cipher algorithm, mode and key file:
$cfg -a server1.net -p 1025 -i $idx -K $hash_key -k $cipher_key
$cfg A add -a server1.net -p 1025 -i $idx -K $hash_key -k $cipher_key

Mount filesystem with given index $idx to /mnt mountpoint.
Client will connect to all servers specified in the working set via previous command:
mount -t pohmel -o idx=$idx q /mnt

One can add or remove servers from working set after mounting too.
Change permissions to read-only (-I 1 option, '-I 2' - write-only, 3 - rw):
$cfg A modify -a server1.net -p 1025 -i $idx -I 1

Change IO priority to 123 (node with the highest priority gets read requests).
$cfg A modify -a server1.net -p 1025 -i $idx -P 123

One can check currect status of all connections in the mountstats file:
# cat /proc/$PID/mountstats
...
device none mounted on /mnt with fstype pohmel
idx addr(:port) socket_type protocol active priority permissions
0 server1.net:1026 1 6 1 250 1
0 server2.net:1025 1 6 1 123 3

Server installation.

+152 −49
Original line number Diff line number Diff line
@@ -41,6 +41,8 @@ static int binder_last_id;
static struct proc_dir_entry *binder_proc_dir_entry_root;
static struct proc_dir_entry *binder_proc_dir_entry_proc;
static struct hlist_head binder_dead_nodes;
static HLIST_HEAD(binder_deferred_list);
static DEFINE_MUTEX(binder_deferred_lock);

static int binder_read_proc_proc(
	char *page, char **start, off_t off, int count, int *eof, void *data);
@@ -54,11 +56,7 @@ static int binder_read_proc_proc(
#define SZ_4M                               0x400000
#endif

#ifndef __i386__
#define FORBIDDEN_MMAP_FLAGS                (VM_WRITE | VM_EXEC)
#else
#define FORBIDDEN_MMAP_FLAGS                (VM_WRITE)
#endif

#define BINDER_SMALL_BUF_SIZE (PAGE_SIZE * 64)

@@ -236,6 +234,12 @@ struct binder_buffer {
	uint8_t data[0];
};

enum {
	BINDER_DEFERRED_PUT_FILES    = 0x01,
	BINDER_DEFERRED_FLUSH        = 0x02,
	BINDER_DEFERRED_RELEASE      = 0x04,
};

struct binder_proc {
	struct hlist_node proc_node;
	struct rb_root threads;
@@ -245,8 +249,11 @@ struct binder_proc {
	int pid;
	struct vm_area_struct *vma;
	struct task_struct *tsk;
	struct files_struct *files;
	struct hlist_node deferred_work_node;
	int deferred_work;
	void *buffer;
	size_t user_buffer_offset;
	ptrdiff_t user_buffer_offset;

	struct list_head buffers;
	struct rb_root free_buffers;
@@ -310,12 +317,14 @@ struct binder_transaction {
	uid_t	sender_euid;
};

static void binder_defer_work(struct binder_proc *proc, int defer);

/*
 * copied from get_unused_fd_flags
 */
int task_get_unused_fd_flags(struct task_struct *tsk, int flags)
int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
{
	struct files_struct *files = get_files_struct(tsk);
	struct files_struct *files = proc->files;
	int fd, error;
	struct fdtable *fdt;
	unsigned long rlim_cur;
@@ -337,9 +346,9 @@ repeat:
	 * will limit the total number of files that can be opened.
	 */
	rlim_cur = 0;
	if (lock_task_sighand(tsk, &irqs)) {
		rlim_cur = tsk->signal->rlim[RLIMIT_NOFILE].rlim_cur;
		unlock_task_sighand(tsk, &irqs);
	if (lock_task_sighand(proc->tsk, &irqs)) {
		rlim_cur = proc->tsk->signal->rlim[RLIMIT_NOFILE].rlim_cur;
		unlock_task_sighand(proc->tsk, &irqs);
	}
	if (fd >= rlim_cur)
		goto out;
@@ -375,7 +384,6 @@ repeat:

out:
	spin_unlock(&files->file_lock);
	put_files_struct(files);
	return error;
}

@@ -383,9 +391,9 @@ out:
 * copied from fd_install
 */
static void task_fd_install(
	struct task_struct *tsk, unsigned int fd, struct file *file)
	struct binder_proc *proc, unsigned int fd, struct file *file)
{
	struct files_struct *files = get_files_struct(tsk);
	struct files_struct *files = proc->files;
	struct fdtable *fdt;

	if (files == NULL)
@@ -396,7 +404,6 @@ static void task_fd_install(
	BUG_ON(fdt->fd[fd] != NULL);
	rcu_assign_pointer(fdt->fd[fd], file);
	spin_unlock(&files->file_lock);
	put_files_struct(files);
}

/*
@@ -413,10 +420,10 @@ static void __put_unused_fd(struct files_struct *files, unsigned int fd)
/*
 * copied from sys_close
 */
static long task_close_fd(struct task_struct *tsk, unsigned int fd)
static long task_close_fd(struct binder_proc *proc, unsigned int fd)
{
	struct file *filp;
	struct files_struct *files = get_files_struct(tsk);
	struct files_struct *files = proc->files;
	struct fdtable *fdt;
	int retval;

@@ -443,12 +450,10 @@ static long task_close_fd(struct task_struct *tsk, unsigned int fd)
		     retval == -ERESTART_RESTARTBLOCK))
		retval = -EINTR;

	put_files_struct(files);
	return retval;

out_unlock:
	spin_unlock(&files->file_lock);
	put_files_struct(files);
	return -EBADF;
}

@@ -618,7 +623,8 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
			       proc->pid, page_addr);
			goto err_map_kernel_failed;
		}
		user_page_addr = (size_t)page_addr + proc->user_buffer_offset;
		user_page_addr =
			(uintptr_t)page_addr + proc->user_buffer_offset;
		ret = vm_insert_page(vma, user_page_addr, page[0]);
		if (ret) {
			printk(KERN_ERR "binder: %d: binder_alloc_buf failed "
@@ -639,7 +645,7 @@ free_range:
	     page_addr -= PAGE_SIZE) {
		page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];
		if (vma)
			zap_page_range(vma, (size_t)page_addr +
			zap_page_range(vma, (uintptr_t)page_addr +
				proc->user_buffer_offset, PAGE_SIZE, NULL);
err_vm_insert_page_failed:
		unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE);
@@ -720,18 +726,19 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,
		       "er %p size %zd\n", proc->pid, size, buffer, buffer_size);

	has_page_addr =
		(void *)(((size_t)buffer->data + buffer_size) & PAGE_MASK);
		(void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK);
	if (n == NULL) {
		if (size + sizeof(struct binder_buffer) + 4 >= buffer_size)
			buffer_size = size; /* no room for other buffers */
		else
			buffer_size = size + sizeof(struct binder_buffer);
	}
	end_page_addr = (void *)PAGE_ALIGN((size_t)buffer->data + buffer_size);
	end_page_addr =
		(void *)PAGE_ALIGN((uintptr_t)buffer->data + buffer_size);
	if (end_page_addr > has_page_addr)
		end_page_addr = has_page_addr;
	if (binder_update_page_range(proc, 1,
	    (void *)PAGE_ALIGN((size_t)buffer->data), end_page_addr, NULL))
	    (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr, NULL))
		return NULL;

	rb_erase(best_fit, &proc->free_buffers);
@@ -762,12 +769,12 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,

static void *buffer_start_page(struct binder_buffer *buffer)
{
	return (void *)((size_t)buffer & PAGE_MASK);
	return (void *)((uintptr_t)buffer & PAGE_MASK);
}

static void *buffer_end_page(struct binder_buffer *buffer)
{
	return (void *)(((size_t)(buffer + 1) - 1) & PAGE_MASK);
	return (void *)(((uintptr_t)(buffer + 1) - 1) & PAGE_MASK);
}

static void binder_delete_free_buffer(
@@ -845,8 +852,8 @@ static void binder_free_buf(
	}

	binder_update_page_range(proc, 0,
		(void *)PAGE_ALIGN((size_t)buffer->data),
		(void *)(((size_t)buffer->data + buffer_size) & PAGE_MASK),
		(void *)PAGE_ALIGN((uintptr_t)buffer->data),
		(void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK),
		NULL);
	rb_erase(&buffer->rb_node, &proc->allocated_buffers);
	buffer->free = 1;
@@ -1345,6 +1352,17 @@ binder_transaction(struct binder_proc *proc, struct binder_thread *thread,
		if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) {
			struct binder_transaction *tmp;
			tmp = thread->transaction_stack;
			if (tmp->to_thread != thread) {
				binder_user_error("binder: %d:%d got new "
					"transaction with bad transaction stack"
					", transaction %d has target %d:%d\n",
					proc->pid, thread->pid, tmp->debug_id,
					tmp->to_proc ? tmp->to_proc->pid : 0,
					tmp->to_thread ?
					tmp->to_thread->pid : 0);
				return_error = BR_FAILED_REPLY;
				goto err_bad_call_stack;
			}
			while (tmp) {
				if (tmp->from && tmp->from->proc == target_proc)
					target_thread = tmp->from;
@@ -1434,10 +1452,19 @@ binder_transaction(struct binder_proc *proc, struct binder_thread *thread,
		return_error = BR_FAILED_REPLY;
		goto err_copy_data_failed;
	}
	if (!IS_ALIGNED(tr->offsets_size, sizeof(size_t))) {
		binder_user_error("binder: %d:%d got transaction with "
			"invalid offsets size, %zd\n",
			proc->pid, thread->pid, tr->offsets_size);
		return_error = BR_FAILED_REPLY;
		goto err_bad_offset;
	}
	off_end = (void *)offp + tr->offsets_size;
	for (; offp < off_end; offp++) {
		struct flat_binder_object *fp;
		if (*offp > t->buffer->data_size - sizeof(*fp)) {
		if (*offp > t->buffer->data_size - sizeof(*fp) ||
		    t->buffer->data_size < sizeof(*fp) ||
		    !IS_ALIGNED(*offp, sizeof(void *))) {
			binder_user_error("binder: %d:%d got transaction with "
				"invalid offset, %zd\n",
				proc->pid, thread->pid, *offp);
@@ -1544,13 +1571,13 @@ binder_transaction(struct binder_proc *proc, struct binder_thread *thread,
				return_error = BR_FAILED_REPLY;
				goto err_fget_failed;
			}
			target_fd = task_get_unused_fd_flags(target_proc->tsk, O_CLOEXEC);
			target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);
			if (target_fd < 0) {
				fput(file);
				return_error = BR_FAILED_REPLY;
				goto err_get_unused_fd_failed;
			}
			task_fd_install(target_proc->tsk, target_fd, file);
			task_fd_install(target_proc, target_fd, file);
			if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)
				printk(KERN_INFO "        fd %ld -> %d\n", fp->handle, target_fd);
			/* TODO: fput? */
@@ -1655,7 +1682,9 @@ binder_transaction_buffer_release(struct binder_proc *proc, struct binder_buffer
		off_end = (void *)offp + buffer->offsets_size;
	for (; offp < off_end; offp++) {
		struct flat_binder_object *fp;
		if (*offp > buffer->data_size - sizeof(*fp)) {
		if (*offp > buffer->data_size - sizeof(*fp) ||
		    buffer->data_size < sizeof(*fp) ||
		    !IS_ALIGNED(*offp, sizeof(void *))) {
			printk(KERN_ERR "binder: transaction release %d bad"
					"offset %zd, size %zd\n", debug_id, *offp, buffer->data_size);
			continue;
@@ -1691,7 +1720,7 @@ binder_transaction_buffer_release(struct binder_proc *proc, struct binder_buffer
			if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)
				printk(KERN_INFO "        fd %ld\n", fp->handle);
			if (failed_at)
				task_close_fd(proc->tsk, fp->handle);
				task_close_fd(proc, fp->handle);
			break;

		default:
@@ -2340,7 +2369,7 @@ retry:

		tr.data_size = t->buffer->data_size;
		tr.offsets_size = t->buffer->offsets_size;
		tr.data.ptr.buffer = (void *)((void *)t->buffer->data + proc->user_buffer_offset);
		tr.data.ptr.buffer = (void *)t->buffer->data + proc->user_buffer_offset;
		tr.data.ptr.offsets = tr.data.ptr.buffer + ALIGN(t->buffer->data_size, sizeof(void *));

		if (put_user(cmd, (uint32_t __user *)ptr))
@@ -2656,6 +2685,7 @@ static void binder_vma_open(struct vm_area_struct *vma)
			(unsigned long)pgprot_val(vma->vm_page_prot));
	dump_stack();
}

static void binder_vma_close(struct vm_area_struct *vma)
{
	struct binder_proc *proc = vma->vm_private_data;
@@ -2666,6 +2696,7 @@ static void binder_vma_close(struct vm_area_struct *vma)
			(vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,
			(unsigned long)pgprot_val(vma->vm_page_prot));
	proc->vma = NULL;
	binder_defer_work(proc, BINDER_DEFERRED_PUT_FILES);
}

static struct vm_operations_struct binder_vm_ops = {
@@ -2698,6 +2729,12 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
	}
	vma->vm_flags = (vma->vm_flags | VM_DONTCOPY) & ~VM_MAYWRITE;

	if (proc->buffer) {
		ret = -EBUSY;
		failure_string = "already mapped";
		goto err_already_mapped;
	}

	area = get_vm_area(vma->vm_end - vma->vm_start, VM_IOREMAP);
	if (area == NULL) {
		ret = -ENOMEM;
@@ -2705,7 +2742,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
		goto err_get_vm_area_failed;
	}
	proc->buffer = area->addr;
	proc->user_buffer_offset = vma->vm_start - (size_t)proc->buffer;
	proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer;

#ifdef CONFIG_CPU_CACHE_VIPT
	if (cache_is_vipt_aliasing()) {
@@ -2738,6 +2775,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
	binder_insert_free_buffer(proc, buffer);
	proc->free_async_space = proc->buffer_size / 2;
	barrier();
	proc->files = get_files_struct(current);
	proc->vma = vma;

	/*printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer);*/
@@ -2745,10 +2783,12 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)

err_alloc_small_buf_failed:
	kfree(proc->pages);
	proc->pages = NULL;
err_alloc_pages_failed:
	vfree(proc->buffer);
	proc->buffer = NULL;
err_get_vm_area_failed:
	mutex_unlock(&binder_lock);
err_already_mapped:
err_bad_arg:
	printk(KERN_ERR "binder_mmap: %d %lx-%lx %s failed %d\n", proc->pid, vma->vm_start, vma->vm_end, failure_string, ret);
	return ret;
@@ -2780,6 +2820,7 @@ static int binder_open(struct inode *nodp, struct file *filp)
	if (binder_proc_dir_entry_proc) {
		char strbuf[11];
		snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
		remove_proc_entry(strbuf, binder_proc_dir_entry_proc);
		create_proc_read_entry(strbuf, S_IRUGO, binder_proc_dir_entry_proc, binder_read_proc_proc, proc);
	}

@@ -2788,11 +2829,17 @@ static int binder_open(struct inode *nodp, struct file *filp)

static int binder_flush(struct file *filp, fl_owner_t id)
{
	struct rb_node *n;
	struct binder_proc *proc = filp->private_data;
	int wake_count = 0;

	mutex_lock(&binder_lock);
	binder_defer_work(proc, BINDER_DEFERRED_FLUSH);

	return 0;
}

static void binder_deferred_flush(struct binder_proc *proc)
{
	struct rb_node *n;
	int wake_count = 0;
	for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) {
		struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node);
		thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN;
@@ -2802,28 +2849,35 @@ static int binder_flush(struct file *filp, fl_owner_t id)
		}
	}
	wake_up_interruptible_all(&proc->wait);
	mutex_unlock(&binder_lock);

	if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE)
		printk(KERN_INFO "binder_flush: %d woke %d threads\n", proc->pid, wake_count);

	return 0;
}

static int binder_release(struct inode *nodp, struct file *filp)
{
	struct hlist_node *pos;
	struct binder_transaction *t;
	struct rb_node *n;
	struct binder_proc *proc = filp->private_data;
	int threads, nodes, incoming_refs, outgoing_refs, buffers, active_transactions, page_count;

	if (binder_proc_dir_entry_proc) {
		char strbuf[11];
		snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
		remove_proc_entry(strbuf, binder_proc_dir_entry_proc);
	}
	mutex_lock(&binder_lock);

	binder_defer_work(proc, BINDER_DEFERRED_RELEASE);

	return 0;
}

static void binder_deferred_release(struct binder_proc *proc)
{
	struct hlist_node *pos;
	struct binder_transaction *t;
	struct rb_node *n;
	int threads, nodes, incoming_refs, outgoing_refs, buffers, active_transactions, page_count;

	BUG_ON(proc->vma);
	BUG_ON(proc->files);

	hlist_del(&proc->proc_node);
	if (binder_context_mgr_node && binder_context_mgr_node->proc == proc) {
		if (binder_debug_mask & BINDER_DEBUG_DEAD_BINDER)
@@ -2897,7 +2951,6 @@ static int binder_release(struct inode *nodp, struct file *filp)
	}

	binder_stats.obj_deleted[BINDER_STAT_PROC]++;
	mutex_unlock(&binder_lock);

	page_count = 0;
	if (proc->pages) {
@@ -2921,7 +2974,57 @@ static int binder_release(struct inode *nodp, struct file *filp)
		       proc->pid, threads, nodes, incoming_refs, outgoing_refs, active_transactions, buffers, page_count);

	kfree(proc);
	return 0;
}

static void binder_deferred_func(struct work_struct *work)
{
	struct binder_proc *proc;
	struct files_struct *files;

	int defer;
	do {
		mutex_lock(&binder_lock);
		mutex_lock(&binder_deferred_lock);
		if (!hlist_empty(&binder_deferred_list)) {
			proc = hlist_entry(binder_deferred_list.first,
					struct binder_proc, deferred_work_node);
			hlist_del_init(&proc->deferred_work_node);
			defer = proc->deferred_work;
			proc->deferred_work = 0;
		} else {
			proc = NULL;
			defer = 0;
		}
		mutex_unlock(&binder_deferred_lock);

		files = NULL;
		if (defer & BINDER_DEFERRED_PUT_FILES)
			if ((files = proc->files))
				proc->files = NULL;

		if (defer & BINDER_DEFERRED_FLUSH)
			binder_deferred_flush(proc);

		if (defer & BINDER_DEFERRED_RELEASE)
			binder_deferred_release(proc); /* frees proc */

		mutex_unlock(&binder_lock);
		if (files)
			put_files_struct(files);
	} while (proc);
}
static DECLARE_WORK(binder_deferred_work, binder_deferred_func);

static void binder_defer_work(struct binder_proc *proc, int defer)
{
	mutex_lock(&binder_deferred_lock);
	proc->deferred_work |= defer;
	if (hlist_unhashed(&proc->deferred_work_node)) {
		hlist_add_head(&proc->deferred_work_node,
				&binder_deferred_list);
		schedule_work(&binder_deferred_work);
	}
	mutex_unlock(&binder_deferred_lock);
}

static char *print_binder_transaction(char *buf, char *end, const char *prefix, struct binder_transaction *t)
+13 −7
Original line number Diff line number Diff line
@@ -5259,6 +5259,18 @@ static int at76_alloc_urbs(struct at76_priv *priv,
	return 0;
}

static const struct net_device_ops at76_netdev_ops = {
	.ndo_open		= at76_open,
	.ndo_stop		= at76_stop,
	.ndo_get_stats		= at76_get_stats,
	.ndo_start_xmit		= at76_tx,
	.ndo_tx_timeout		= at76_tx_timeout,
	.ndo_set_multicast_list	= at76_set_multicast,
	.ndo_set_mac_address	= at76_set_mac_address,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_change_mtu		= eth_change_mtu,
};

/* Register network device and initialize the hardware */
static int at76_init_new_device(struct at76_priv *priv,
				struct usb_interface *interface)
@@ -5303,21 +5315,15 @@ static int at76_init_new_device(struct at76_priv *priv,
	priv->scan_mode = SCAN_TYPE_ACTIVE;

	netdev->flags &= ~IFF_MULTICAST;	/* not yet or never */
	netdev->open = at76_open;
	netdev->stop = at76_stop;
	netdev->get_stats = at76_get_stats;
	netdev->netdev_ops = &at76_netdev_ops;
	netdev->ethtool_ops = &at76_ethtool_ops;

	/* Add pointers to enable iwspy support. */
	priv->wireless_data.spy_data = &priv->spy_data;
	netdev->wireless_data = &priv->wireless_data;

	netdev->hard_start_xmit = at76_tx;
	netdev->tx_timeout = at76_tx_timeout;
	netdev->watchdog_timeo = 2 * HZ;
	netdev->wireless_handlers = &at76_handler_def;
	netdev->set_multicast_list = at76_set_multicast;
	netdev->set_mac_address = at76_set_mac_address;
	dev_alloc_name(netdev, "wlan%d");

	ret = register_netdev(priv->netdev);
+12 −5
Original line number Diff line number Diff line
@@ -284,6 +284,17 @@ static tEplKernel VEthRecvFrame(tEplFrameInfo * pFrameInfo_p)
	return Ret;
}

static const struct net_device_ops epl_netdev_ops = {
	.ndo_open		= VEthOpen,
	.ndo_stop		= VEthClose,
	.ndo_get_stats		= VEthGetStats,
	.ndo_start_xmit		= VEthXmit,
	.ndo_tx_timeout		= VEthTimeout,
	.ndo_change_mtu		= eth_change_mtu,
	.ndo_set_mac_address	= eth_mac_addr,
	.ndo_validate_addr	= eth_validate_addr,
};

tEplKernel VEthAddInstance(tEplDllkInitParam *pInitParam_p)
{
	tEplKernel Ret = kEplSuccessful;
@@ -299,11 +310,7 @@ tEplKernel VEthAddInstance(tEplDllkInitParam *pInitParam_p)
		goto Exit;
	}

	pVEthNetDevice_g->open = VEthOpen;
	pVEthNetDevice_g->stop = VEthClose;
	pVEthNetDevice_g->get_stats = VEthGetStats;
	pVEthNetDevice_g->hard_start_xmit = VEthXmit;
	pVEthNetDevice_g->tx_timeout = VEthTimeout;
	pVEthNetDevice_g->netdev_ops = &epl_netdev_ops;
	pVEthNetDevice_g->watchdog_timeo = EPL_VETH_TX_TIMEOUT;
	pVEthNetDevice_g->destructor = free_netdev;

Loading