aboutsummaryrefslogtreecommitdiffstats
path: root/net/can
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /net/can
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'net/can')
-rw-r--r--net/can/Makefile6
-rw-r--r--net/can/af_can.c76
-rw-r--r--net/can/bcm.c28
-rw-r--r--net/can/proc.c7
-rw-r--r--net/can/raw.c53
5 files changed, 113 insertions, 57 deletions
diff --git a/net/can/Makefile b/net/can/Makefile
index 9cd3c4b3abda..2d3894b32742 100644
--- a/net/can/Makefile
+++ b/net/can/Makefile
@@ -3,10 +3,10 @@
3# 3#
4 4
5obj-$(CONFIG_CAN) += can.o 5obj-$(CONFIG_CAN) += can.o
6can-objs := af_can.o proc.o 6can-y := af_can.o proc.o
7 7
8obj-$(CONFIG_CAN_RAW) += can-raw.o 8obj-$(CONFIG_CAN_RAW) += can-raw.o
9can-raw-objs := raw.o 9can-raw-y := raw.o
10 10
11obj-$(CONFIG_CAN_BCM) += can-bcm.o 11obj-$(CONFIG_CAN_BCM) += can-bcm.o
12can-bcm-objs := bcm.o 12can-bcm-y := bcm.o
diff --git a/net/can/af_can.c b/net/can/af_can.c
index 702be5a2c956..094fc5332d42 100644
--- a/net/can/af_can.c
+++ b/net/can/af_can.c
@@ -84,8 +84,8 @@ static DEFINE_SPINLOCK(can_rcvlists_lock);
84static struct kmem_cache *rcv_cache __read_mostly; 84static struct kmem_cache *rcv_cache __read_mostly;
85 85
86/* table of registered CAN protocols */ 86/* table of registered CAN protocols */
87static struct can_proto *proto_tab[CAN_NPROTO] __read_mostly; 87static const struct can_proto *proto_tab[CAN_NPROTO] __read_mostly;
88static DEFINE_SPINLOCK(proto_tab_lock); 88static DEFINE_MUTEX(proto_tab_lock);
89 89
90struct timer_list can_stattimer; /* timer for statistics update */ 90struct timer_list can_stattimer; /* timer for statistics update */
91struct s_stats can_stats; /* packet statistics */ 91struct s_stats can_stats; /* packet statistics */
@@ -95,7 +95,7 @@ struct s_pstats can_pstats; /* receive list statistics */
95 * af_can socket functions 95 * af_can socket functions
96 */ 96 */
97 97
98static int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) 98int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
99{ 99{
100 struct sock *sk = sock->sk; 100 struct sock *sk = sock->sk;
101 101
@@ -108,17 +108,36 @@ static int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
108 return -ENOIOCTLCMD; 108 return -ENOIOCTLCMD;
109 } 109 }
110} 110}
111EXPORT_SYMBOL(can_ioctl);
111 112
112static void can_sock_destruct(struct sock *sk) 113static void can_sock_destruct(struct sock *sk)
113{ 114{
114 skb_queue_purge(&sk->sk_receive_queue); 115 skb_queue_purge(&sk->sk_receive_queue);
115} 116}
116 117
118static const struct can_proto *can_get_proto(int protocol)
119{
120 const struct can_proto *cp;
121
122 rcu_read_lock();
123 cp = rcu_dereference(proto_tab[protocol]);
124 if (cp && !try_module_get(cp->prot->owner))
125 cp = NULL;
126 rcu_read_unlock();
127
128 return cp;
129}
130
131static inline void can_put_proto(const struct can_proto *cp)
132{
133 module_put(cp->prot->owner);
134}
135
117static int can_create(struct net *net, struct socket *sock, int protocol, 136static int can_create(struct net *net, struct socket *sock, int protocol,
118 int kern) 137 int kern)
119{ 138{
120 struct sock *sk; 139 struct sock *sk;
121 struct can_proto *cp; 140 const struct can_proto *cp;
122 int err = 0; 141 int err = 0;
123 142
124 sock->state = SS_UNCONNECTED; 143 sock->state = SS_UNCONNECTED;
@@ -129,9 +148,12 @@ static int can_create(struct net *net, struct socket *sock, int protocol,
129 if (!net_eq(net, &init_net)) 148 if (!net_eq(net, &init_net))
130 return -EAFNOSUPPORT; 149 return -EAFNOSUPPORT;
131 150
151 cp = can_get_proto(protocol);
152
132#ifdef CONFIG_MODULES 153#ifdef CONFIG_MODULES
133 /* try to load protocol module kernel is modular */ 154 if (!cp) {
134 if (!proto_tab[protocol]) { 155 /* try to load protocol module if kernel is modular */
156
135 err = request_module("can-proto-%d", protocol); 157 err = request_module("can-proto-%d", protocol);
136 158
137 /* 159 /*
@@ -142,22 +164,18 @@ static int can_create(struct net *net, struct socket *sock, int protocol,
142 if (err && printk_ratelimit()) 164 if (err && printk_ratelimit())
143 printk(KERN_ERR "can: request_module " 165 printk(KERN_ERR "can: request_module "
144 "(can-proto-%d) failed.\n", protocol); 166 "(can-proto-%d) failed.\n", protocol);
167
168 cp = can_get_proto(protocol);
145 } 169 }
146#endif 170#endif
147 171
148 spin_lock(&proto_tab_lock);
149 cp = proto_tab[protocol];
150 if (cp && !try_module_get(cp->prot->owner))
151 cp = NULL;
152 spin_unlock(&proto_tab_lock);
153
154 /* check for available protocol and correct usage */ 172 /* check for available protocol and correct usage */
155 173
156 if (!cp) 174 if (!cp)
157 return -EPROTONOSUPPORT; 175 return -EPROTONOSUPPORT;
158 176
159 if (cp->type != sock->type) { 177 if (cp->type != sock->type) {
160 err = -EPROTONOSUPPORT; 178 err = -EPROTOTYPE;
161 goto errout; 179 goto errout;
162 } 180 }
163 181
@@ -182,7 +200,7 @@ static int can_create(struct net *net, struct socket *sock, int protocol,
182 } 200 }
183 201
184 errout: 202 errout:
185 module_put(cp->prot->owner); 203 can_put_proto(cp);
186 return err; 204 return err;
187} 205}
188 206
@@ -678,7 +696,7 @@ drop:
678 * -EBUSY protocol already in use 696 * -EBUSY protocol already in use
679 * -ENOBUF if proto_register() fails 697 * -ENOBUF if proto_register() fails
680 */ 698 */
681int can_proto_register(struct can_proto *cp) 699int can_proto_register(const struct can_proto *cp)
682{ 700{
683 int proto = cp->protocol; 701 int proto = cp->protocol;
684 int err = 0; 702 int err = 0;
@@ -693,19 +711,16 @@ int can_proto_register(struct can_proto *cp)
693 if (err < 0) 711 if (err < 0)
694 return err; 712 return err;
695 713
696 spin_lock(&proto_tab_lock); 714 mutex_lock(&proto_tab_lock);
715
697 if (proto_tab[proto]) { 716 if (proto_tab[proto]) {
698 printk(KERN_ERR "can: protocol %d already registered\n", 717 printk(KERN_ERR "can: protocol %d already registered\n",
699 proto); 718 proto);
700 err = -EBUSY; 719 err = -EBUSY;
701 } else { 720 } else
702 proto_tab[proto] = cp; 721 rcu_assign_pointer(proto_tab[proto], cp);
703 722
704 /* use generic ioctl function if not defined by module */ 723 mutex_unlock(&proto_tab_lock);
705 if (!cp->ops->ioctl)
706 cp->ops->ioctl = can_ioctl;
707 }
708 spin_unlock(&proto_tab_lock);
709 724
710 if (err < 0) 725 if (err < 0)
711 proto_unregister(cp->prot); 726 proto_unregister(cp->prot);
@@ -718,17 +733,16 @@ EXPORT_SYMBOL(can_proto_register);
718 * can_proto_unregister - unregister CAN transport protocol 733 * can_proto_unregister - unregister CAN transport protocol
719 * @cp: pointer to CAN protocol structure 734 * @cp: pointer to CAN protocol structure
720 */ 735 */
721void can_proto_unregister(struct can_proto *cp) 736void can_proto_unregister(const struct can_proto *cp)
722{ 737{
723 int proto = cp->protocol; 738 int proto = cp->protocol;
724 739
725 spin_lock(&proto_tab_lock); 740 mutex_lock(&proto_tab_lock);
726 if (!proto_tab[proto]) { 741 BUG_ON(proto_tab[proto] != cp);
727 printk(KERN_ERR "BUG: can: protocol %d is not registered\n", 742 rcu_assign_pointer(proto_tab[proto], NULL);
728 proto); 743 mutex_unlock(&proto_tab_lock);
729 } 744
730 proto_tab[proto] = NULL; 745 synchronize_rcu();
731 spin_unlock(&proto_tab_lock);
732 746
733 proto_unregister(cp->prot); 747 proto_unregister(cp->prot);
734} 748}
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 08ffe9e4be20..184a6572b67e 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -125,7 +125,7 @@ struct bcm_sock {
125 struct list_head tx_ops; 125 struct list_head tx_ops;
126 unsigned long dropped_usr_msgs; 126 unsigned long dropped_usr_msgs;
127 struct proc_dir_entry *bcm_proc_read; 127 struct proc_dir_entry *bcm_proc_read;
128 char procname [9]; /* pointer printed in ASCII with \0 */ 128 char procname [32]; /* inode number in decimal with \0 */
129}; 129};
130 130
131static inline struct bcm_sock *bcm_sk(const struct sock *sk) 131static inline struct bcm_sock *bcm_sk(const struct sock *sk)
@@ -165,9 +165,9 @@ static int bcm_proc_show(struct seq_file *m, void *v)
165 struct bcm_sock *bo = bcm_sk(sk); 165 struct bcm_sock *bo = bcm_sk(sk);
166 struct bcm_op *op; 166 struct bcm_op *op;
167 167
168 seq_printf(m, ">>> socket %p", sk->sk_socket); 168 seq_printf(m, ">>> socket %pK", sk->sk_socket);
169 seq_printf(m, " / sk %p", sk); 169 seq_printf(m, " / sk %pK", sk);
170 seq_printf(m, " / bo %p", bo); 170 seq_printf(m, " / bo %pK", bo);
171 seq_printf(m, " / dropped %lu", bo->dropped_usr_msgs); 171 seq_printf(m, " / dropped %lu", bo->dropped_usr_msgs);
172 seq_printf(m, " / bound %s", bcm_proc_getifname(ifname, bo->ifindex)); 172 seq_printf(m, " / bound %s", bcm_proc_getifname(ifname, bo->ifindex));
173 seq_printf(m, " <<<\n"); 173 seq_printf(m, " <<<\n");
@@ -387,7 +387,7 @@ static void bcm_tx_timeout_tsklet(unsigned long data)
387} 387}
388 388
389/* 389/*
390 * bcm_tx_timeout_handler - performes cyclic CAN frame transmissions 390 * bcm_tx_timeout_handler - performs cyclic CAN frame transmissions
391 */ 391 */
392static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer) 392static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer)
393{ 393{
@@ -1256,6 +1256,9 @@ static int bcm_sendmsg(struct kiocb *iocb, struct socket *sock,
1256 struct sockaddr_can *addr = 1256 struct sockaddr_can *addr =
1257 (struct sockaddr_can *)msg->msg_name; 1257 (struct sockaddr_can *)msg->msg_name;
1258 1258
1259 if (msg->msg_namelen < sizeof(*addr))
1260 return -EINVAL;
1261
1259 if (addr->can_family != AF_CAN) 1262 if (addr->can_family != AF_CAN)
1260 return -EINVAL; 1263 return -EINVAL;
1261 1264
@@ -1424,9 +1427,14 @@ static int bcm_init(struct sock *sk)
1424static int bcm_release(struct socket *sock) 1427static int bcm_release(struct socket *sock)
1425{ 1428{
1426 struct sock *sk = sock->sk; 1429 struct sock *sk = sock->sk;
1427 struct bcm_sock *bo = bcm_sk(sk); 1430 struct bcm_sock *bo;
1428 struct bcm_op *op, *next; 1431 struct bcm_op *op, *next;
1429 1432
1433 if (sk == NULL)
1434 return 0;
1435
1436 bo = bcm_sk(sk);
1437
1430 /* remove bcm_ops, timer, rx_unregister(), etc. */ 1438 /* remove bcm_ops, timer, rx_unregister(), etc. */
1431 1439
1432 unregister_netdevice_notifier(&bo->notifier); 1440 unregister_netdevice_notifier(&bo->notifier);
@@ -1521,7 +1529,7 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len,
1521 1529
1522 if (proc_dir) { 1530 if (proc_dir) {
1523 /* unique socket address as filename */ 1531 /* unique socket address as filename */
1524 sprintf(bo->procname, "%p", sock); 1532 sprintf(bo->procname, "%lu", sock_i_ino(sk));
1525 bo->bcm_proc_read = proc_create_data(bo->procname, 0644, 1533 bo->bcm_proc_read = proc_create_data(bo->procname, 0644,
1526 proc_dir, 1534 proc_dir,
1527 &bcm_proc_fops, sk); 1535 &bcm_proc_fops, sk);
@@ -1566,7 +1574,7 @@ static int bcm_recvmsg(struct kiocb *iocb, struct socket *sock,
1566 return size; 1574 return size;
1567} 1575}
1568 1576
1569static struct proto_ops bcm_ops __read_mostly = { 1577static const struct proto_ops bcm_ops = {
1570 .family = PF_CAN, 1578 .family = PF_CAN,
1571 .release = bcm_release, 1579 .release = bcm_release,
1572 .bind = sock_no_bind, 1580 .bind = sock_no_bind,
@@ -1575,7 +1583,7 @@ static struct proto_ops bcm_ops __read_mostly = {
1575 .accept = sock_no_accept, 1583 .accept = sock_no_accept,
1576 .getname = sock_no_getname, 1584 .getname = sock_no_getname,
1577 .poll = datagram_poll, 1585 .poll = datagram_poll,
1578 .ioctl = NULL, /* use can_ioctl() from af_can.c */ 1586 .ioctl = can_ioctl, /* use can_ioctl() from af_can.c */
1579 .listen = sock_no_listen, 1587 .listen = sock_no_listen,
1580 .shutdown = sock_no_shutdown, 1588 .shutdown = sock_no_shutdown,
1581 .setsockopt = sock_no_setsockopt, 1589 .setsockopt = sock_no_setsockopt,
@@ -1593,7 +1601,7 @@ static struct proto bcm_proto __read_mostly = {
1593 .init = bcm_init, 1601 .init = bcm_init,
1594}; 1602};
1595 1603
1596static struct can_proto bcm_can_proto __read_mostly = { 1604static const struct can_proto bcm_can_proto = {
1597 .type = SOCK_DGRAM, 1605 .type = SOCK_DGRAM,
1598 .protocol = CAN_BCM, 1606 .protocol = CAN_BCM,
1599 .ops = &bcm_ops, 1607 .ops = &bcm_ops,
diff --git a/net/can/proc.c b/net/can/proc.c
index f4265cc9c3fb..0016f7339699 100644
--- a/net/can/proc.c
+++ b/net/can/proc.c
@@ -204,12 +204,11 @@ static void can_print_rcvlist(struct seq_file *m, struct hlist_head *rx_list,
204 204
205 hlist_for_each_entry_rcu(r, n, rx_list, list) { 205 hlist_for_each_entry_rcu(r, n, rx_list, list) {
206 char *fmt = (r->can_id & CAN_EFF_FLAG)? 206 char *fmt = (r->can_id & CAN_EFF_FLAG)?
207 " %-5s %08X %08x %08x %08x %8ld %s\n" : 207 " %-5s %08x %08x %pK %pK %8ld %s\n" :
208 " %-5s %03X %08x %08lx %08lx %8ld %s\n"; 208 " %-5s %03x %08x %pK %pK %8ld %s\n";
209 209
210 seq_printf(m, fmt, DNAME(dev), r->can_id, r->mask, 210 seq_printf(m, fmt, DNAME(dev), r->can_id, r->mask,
211 (unsigned long)r->func, (unsigned long)r->data, 211 r->func, r->data, r->matches, r->ident);
212 r->matches, r->ident);
213 } 212 }
214} 213}
215 214
diff --git a/net/can/raw.c b/net/can/raw.c
index a10e3338f084..dea99a6e596c 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -90,23 +90,39 @@ struct raw_sock {
90 can_err_mask_t err_mask; 90 can_err_mask_t err_mask;
91}; 91};
92 92
93/*
94 * Return pointer to store the extra msg flags for raw_recvmsg().
95 * We use the space of one unsigned int beyond the 'struct sockaddr_can'
96 * in skb->cb.
97 */
98static inline unsigned int *raw_flags(struct sk_buff *skb)
99{
100 BUILD_BUG_ON(sizeof(skb->cb) <= (sizeof(struct sockaddr_can) +
101 sizeof(unsigned int)));
102
103 /* return pointer after struct sockaddr_can */
104 return (unsigned int *)(&((struct sockaddr_can *)skb->cb)[1]);
105}
106
93static inline struct raw_sock *raw_sk(const struct sock *sk) 107static inline struct raw_sock *raw_sk(const struct sock *sk)
94{ 108{
95 return (struct raw_sock *)sk; 109 return (struct raw_sock *)sk;
96} 110}
97 111
98static void raw_rcv(struct sk_buff *skb, void *data) 112static void raw_rcv(struct sk_buff *oskb, void *data)
99{ 113{
100 struct sock *sk = (struct sock *)data; 114 struct sock *sk = (struct sock *)data;
101 struct raw_sock *ro = raw_sk(sk); 115 struct raw_sock *ro = raw_sk(sk);
102 struct sockaddr_can *addr; 116 struct sockaddr_can *addr;
117 struct sk_buff *skb;
118 unsigned int *pflags;
103 119
104 /* check the received tx sock reference */ 120 /* check the received tx sock reference */
105 if (!ro->recv_own_msgs && skb->sk == sk) 121 if (!ro->recv_own_msgs && oskb->sk == sk)
106 return; 122 return;
107 123
108 /* clone the given skb to be able to enqueue it into the rcv queue */ 124 /* clone the given skb to be able to enqueue it into the rcv queue */
109 skb = skb_clone(skb, GFP_ATOMIC); 125 skb = skb_clone(oskb, GFP_ATOMIC);
110 if (!skb) 126 if (!skb)
111 return; 127 return;
112 128
@@ -123,6 +139,14 @@ static void raw_rcv(struct sk_buff *skb, void *data)
123 addr->can_family = AF_CAN; 139 addr->can_family = AF_CAN;
124 addr->can_ifindex = skb->dev->ifindex; 140 addr->can_ifindex = skb->dev->ifindex;
125 141
142 /* add CAN specific message flags for raw_recvmsg() */
143 pflags = raw_flags(skb);
144 *pflags = 0;
145 if (oskb->sk)
146 *pflags |= MSG_DONTROUTE;
147 if (oskb->sk == sk)
148 *pflags |= MSG_CONFIRM;
149
126 if (sock_queue_rcv_skb(sk, skb) < 0) 150 if (sock_queue_rcv_skb(sk, skb) < 0)
127 kfree_skb(skb); 151 kfree_skb(skb);
128} 152}
@@ -281,7 +305,12 @@ static int raw_init(struct sock *sk)
281static int raw_release(struct socket *sock) 305static int raw_release(struct socket *sock)
282{ 306{
283 struct sock *sk = sock->sk; 307 struct sock *sk = sock->sk;
284 struct raw_sock *ro = raw_sk(sk); 308 struct raw_sock *ro;
309
310 if (!sk)
311 return 0;
312
313 ro = raw_sk(sk);
285 314
286 unregister_netdevice_notifier(&ro->notifier); 315 unregister_netdevice_notifier(&ro->notifier);
287 316
@@ -625,6 +654,9 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
625 struct sockaddr_can *addr = 654 struct sockaddr_can *addr =
626 (struct sockaddr_can *)msg->msg_name; 655 (struct sockaddr_can *)msg->msg_name;
627 656
657 if (msg->msg_namelen < sizeof(*addr))
658 return -EINVAL;
659
628 if (addr->can_family != AF_CAN) 660 if (addr->can_family != AF_CAN)
629 return -EINVAL; 661 return -EINVAL;
630 662
@@ -647,12 +679,12 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
647 err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); 679 err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
648 if (err < 0) 680 if (err < 0)
649 goto free_skb; 681 goto free_skb;
650 err = sock_tx_timestamp(msg, sk, skb_tx(skb)); 682 err = sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags);
651 if (err < 0) 683 if (err < 0)
652 goto free_skb; 684 goto free_skb;
653 685
654 /* to be able to check the received tx sock reference in raw_rcv() */ 686 /* to be able to check the received tx sock reference in raw_rcv() */
655 skb_tx(skb)->prevent_sk_orphan = 1; 687 skb_shinfo(skb)->tx_flags |= SKBTX_DRV_NEEDS_SK_REF;
656 688
657 skb->dev = dev; 689 skb->dev = dev;
658 skb->sk = sk; 690 skb->sk = sk;
@@ -707,12 +739,15 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock,
707 memcpy(msg->msg_name, skb->cb, msg->msg_namelen); 739 memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
708 } 740 }
709 741
742 /* assign the flags that have been recorded in raw_rcv() */
743 msg->msg_flags |= *(raw_flags(skb));
744
710 skb_free_datagram(sk, skb); 745 skb_free_datagram(sk, skb);
711 746
712 return size; 747 return size;
713} 748}
714 749
715static struct proto_ops raw_ops __read_mostly = { 750static const struct proto_ops raw_ops = {
716 .family = PF_CAN, 751 .family = PF_CAN,
717 .release = raw_release, 752 .release = raw_release,
718 .bind = raw_bind, 753 .bind = raw_bind,
@@ -721,7 +756,7 @@ static struct proto_ops raw_ops __read_mostly = {
721 .accept = sock_no_accept, 756 .accept = sock_no_accept,
722 .getname = raw_getname, 757 .getname = raw_getname,
723 .poll = datagram_poll, 758 .poll = datagram_poll,
724 .ioctl = NULL, /* use can_ioctl() from af_can.c */ 759 .ioctl = can_ioctl, /* use can_ioctl() from af_can.c */
725 .listen = sock_no_listen, 760 .listen = sock_no_listen,
726 .shutdown = sock_no_shutdown, 761 .shutdown = sock_no_shutdown,
727 .setsockopt = raw_setsockopt, 762 .setsockopt = raw_setsockopt,
@@ -739,7 +774,7 @@ static struct proto raw_proto __read_mostly = {
739 .init = raw_init, 774 .init = raw_init,
740}; 775};
741 776
742static struct can_proto raw_can_proto __read_mostly = { 777static const struct can_proto raw_can_proto = {
743 .type = SOCK_RAW, 778 .type = SOCK_RAW,
744 .protocol = CAN_RAW, 779 .protocol = CAN_RAW,
745 .ops = &raw_ops, 780 .ops = &raw_ops,