Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'for-davem' of git://gitorious.org/linux-can/linux-can-next

Marc Kleine-Budde says:

====================
this is a pull request for net-next. There are two patches from Gerhard
Sittig, which improves the clock handling on mpc5121. Oliver Hartkopp
provides a patch that adds a per rule limitation of frame hops.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+82 -13
+16 -7
drivers/net/can/mscan/mpc5xxx_can.c
··· 40 40 unsigned int type; 41 41 u32 (*get_clock)(struct platform_device *ofdev, const char *clock_name, 42 42 int *mscan_clksrc); 43 + void (*put_clock)(struct platform_device *ofdev); 43 44 }; 44 45 45 46 #ifdef CONFIG_PPC_MPC52xx ··· 149 148 goto exit_put; 150 149 } 151 150 152 - /* Determine the MSCAN device index from the physical address */ 151 + /* Determine the MSCAN device index from the peripheral's 152 + * physical address. Register address offsets against the 153 + * IMMR base are: 0x1300, 0x1380, 0x2300, 0x2380 154 + */ 153 155 pval = of_get_property(ofdev->dev.of_node, "reg", &plen); 154 156 BUG_ON(!pval || plen < sizeof(*pval)); 155 157 clockidx = (*pval & 0x80) ? 1 : 0; ··· 181 177 clockdiv = 1; 182 178 183 179 if (!clock_name || !strcmp(clock_name, "sys")) { 184 - sys_clk = clk_get(&ofdev->dev, "sys_clk"); 180 + sys_clk = devm_clk_get(&ofdev->dev, "sys_clk"); 185 181 if (IS_ERR(sys_clk)) { 186 182 dev_err(&ofdev->dev, "couldn't get sys_clk\n"); 187 183 goto exit_unmap; ··· 204 200 } 205 201 206 202 if (clocksrc < 0) { 207 - ref_clk = clk_get(&ofdev->dev, "ref_clk"); 203 + ref_clk = devm_clk_get(&ofdev->dev, "ref_clk"); 208 204 if (IS_ERR(ref_clk)) { 209 205 dev_err(&ofdev->dev, "couldn't get ref_clk\n"); 210 206 goto exit_unmap; ··· 281 277 dev = alloc_mscandev(); 282 278 if (!dev) 283 279 goto exit_dispose_irq; 280 + platform_set_drvdata(ofdev, dev); 281 + SET_NETDEV_DEV(dev, &ofdev->dev); 284 282 285 283 priv = netdev_priv(dev); 286 284 priv->reg_base = base; ··· 299 293 goto exit_free_mscan; 300 294 } 301 295 302 - SET_NETDEV_DEV(dev, &ofdev->dev); 303 - 304 296 err = register_mscandev(dev, mscan_clksrc); 305 297 if (err) { 306 298 dev_err(&ofdev->dev, "registering %s failed (err=%d)\n", 307 299 DRV_NAME, err); 308 300 goto exit_free_mscan; 309 301 } 310 - 311 - platform_set_drvdata(ofdev, dev); 312 302 313 303 dev_info(&ofdev->dev, "MSCAN at 0x%p, irq %d, clock %d Hz\n", 314 304 priv->reg_base, dev->irq, priv->can.clock.freq); ··· 323 321 324 322 static int mpc5xxx_can_remove(struct platform_device *ofdev) 325 323 { 324 + const struct of_device_id *match; 325 + const struct mpc5xxx_can_data *data; 326 326 struct net_device *dev = platform_get_drvdata(ofdev); 327 327 struct mscan_priv *priv = netdev_priv(dev); 328 328 329 + match = of_match_device(mpc5xxx_can_table, &ofdev->dev); 330 + data = match ? match->data : NULL; 331 + 329 332 unregister_mscandev(dev); 333 + if (data && data->put_clock) 334 + data->put_clock(ofdev); 330 335 iounmap(priv->reg_base); 331 336 irq_dispose_mapping(dev->irq); 332 337 free_candev(dev);
+24 -1
drivers/net/can/mscan/mscan.c
··· 573 573 struct mscan_priv *priv = netdev_priv(dev); 574 574 struct mscan_regs __iomem *regs = priv->reg_base; 575 575 576 + if (priv->clk_ipg) { 577 + ret = clk_prepare_enable(priv->clk_ipg); 578 + if (ret) 579 + goto exit_retcode; 580 + } 581 + if (priv->clk_can) { 582 + ret = clk_prepare_enable(priv->clk_can); 583 + if (ret) 584 + goto exit_dis_ipg_clock; 585 + } 586 + 576 587 /* common open */ 577 588 ret = open_candev(dev); 578 589 if (ret) 579 - return ret; 590 + goto exit_dis_can_clock; 580 591 581 592 napi_enable(&priv->napi); 582 593 ··· 615 604 exit_napi_disable: 616 605 napi_disable(&priv->napi); 617 606 close_candev(dev); 607 + exit_dis_can_clock: 608 + if (priv->clk_can) 609 + clk_disable_unprepare(priv->clk_can); 610 + exit_dis_ipg_clock: 611 + if (priv->clk_ipg) 612 + clk_disable_unprepare(priv->clk_ipg); 613 + exit_retcode: 618 614 return ret; 619 615 } 620 616 ··· 638 620 mscan_set_mode(dev, MSCAN_INIT_MODE); 639 621 close_candev(dev); 640 622 free_irq(dev->irq, dev); 623 + 624 + if (priv->clk_can) 625 + clk_disable_unprepare(priv->clk_can); 626 + if (priv->clk_ipg) 627 + clk_disable_unprepare(priv->clk_ipg); 641 628 642 629 return 0; 643 630 }
+3
drivers/net/can/mscan/mscan.h
··· 21 21 #ifndef __MSCAN_H__ 22 22 #define __MSCAN_H__ 23 23 24 + #include <linux/clk.h> 24 25 #include <linux/types.h> 25 26 26 27 /* MSCAN control register 0 (CANCTL0) bits */ ··· 284 283 unsigned int type; /* MSCAN type variants */ 285 284 unsigned long flags; 286 285 void __iomem *reg_base; /* ioremap'ed address to registers */ 286 + struct clk *clk_ipg; /* clock for registers */ 287 + struct clk *clk_can; /* clock for bitrates */ 287 288 u8 shadow_statflg; 288 289 u8 shadow_canrier; 289 290 u8 cur_pri;
+8 -1
include/uapi/linux/can/gw.h
··· 45 45 CGW_DST_IF, /* ifindex of destination network interface */ 46 46 CGW_FILTER, /* specify struct can_filter on source CAN device */ 47 47 CGW_DELETED, /* number of deleted CAN frames (see max_hops param) */ 48 + CGW_LIM_HOPS, /* limit the number of hops of this specific rule */ 48 49 __CGW_MAX 49 50 }; 50 51 ··· 117 116 * Sets a CAN receive filter for the gateway job specified by the 118 117 * struct can_filter described in include/linux/can.h 119 118 * 120 - * CGW_MOD_XXX (length 17 bytes): 119 + * CGW_MOD_(AND|OR|XOR|SET) (length 17 bytes): 121 120 * Specifies a modification that's done to a received CAN frame before it is 122 121 * send out to the destination interface. 123 122 * 124 123 * <struct can_frame> data used as operator 125 124 * <u8> affected CAN frame elements 125 + * 126 + * CGW_LIM_HOPS (length 1 byte): 127 + * Limit the number of hops of this specific rule. Usually the received CAN 128 + * frame can be processed as much as 'max_hops' times (which is given at module 129 + * load time of the can-gw module). This value is used to reduce the number of 130 + * possible hops for this gateway rule to a value smaller then max_hops. 126 131 * 127 132 * CGW_CS_XOR (length 4 bytes): 128 133 * Set a simple XOR checksum starting with an initial value into
+31 -4
net/can/gw.c
··· 146 146 /* tbc */ 147 147 }; 148 148 u8 gwtype; 149 + u8 limit_hops; 149 150 u16 flags; 150 151 }; 151 152 ··· 403 402 404 403 /* put the incremented hop counter in the cloned skb */ 405 404 cgw_hops(nskb) = cgw_hops(skb) + 1; 405 + 406 + /* first processing of this CAN frame -> adjust to private hop limit */ 407 + if (gwj->limit_hops && cgw_hops(nskb) == 1) 408 + cgw_hops(nskb) = max_hops - gwj->limit_hops + 1; 409 + 406 410 nskb->dev = gwj->dst.dev; 407 411 408 412 /* pointer to modifiable CAN frame */ ··· 515 509 516 510 /* check non default settings of attributes */ 517 511 512 + if (gwj->limit_hops) { 513 + if (nla_put_u8(skb, CGW_LIM_HOPS, gwj->limit_hops) < 0) 514 + goto cancel; 515 + } 516 + 518 517 if (gwj->mod.modtype.and) { 519 518 memcpy(&mb.cf, &gwj->mod.modframe.and, sizeof(mb.cf)); 520 519 mb.modtype = gwj->mod.modtype.and; ··· 617 606 [CGW_SRC_IF] = { .type = NLA_U32 }, 618 607 [CGW_DST_IF] = { .type = NLA_U32 }, 619 608 [CGW_FILTER] = { .len = sizeof(struct can_filter) }, 609 + [CGW_LIM_HOPS] = { .type = NLA_U8 }, 620 610 }; 621 611 622 612 /* check for common and gwtype specific attributes */ 623 613 static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, 624 - u8 gwtype, void *gwtypeattr) 614 + u8 gwtype, void *gwtypeattr, u8 *limhops) 625 615 { 626 616 struct nlattr *tb[CGW_MAX+1]; 627 617 struct cgw_frame_mod mb; ··· 636 624 cgw_policy); 637 625 if (err < 0) 638 626 return err; 627 + 628 + if (tb[CGW_LIM_HOPS]) { 629 + *limhops = nla_get_u8(tb[CGW_LIM_HOPS]); 630 + 631 + if (*limhops < 1 || *limhops > max_hops) 632 + return -EINVAL; 633 + } 639 634 640 635 /* check for AND/OR/XOR/SET modifications */ 641 636 ··· 801 782 { 802 783 struct rtcanmsg *r; 803 784 struct cgw_job *gwj; 785 + u8 limhops = 0; 804 786 int err = 0; 805 787 806 788 if (!capable(CAP_NET_ADMIN)) ··· 828 808 gwj->flags = r->flags; 829 809 gwj->gwtype = r->gwtype; 830 810 831 - err = cgw_parse_attr(nlh, &gwj->mod, CGW_TYPE_CAN_CAN, &gwj->ccgw); 811 + err = cgw_parse_attr(nlh, &gwj->mod, CGW_TYPE_CAN_CAN, &gwj->ccgw, 812 + &limhops); 832 813 if (err < 0) 833 814 goto out; 834 815 ··· 856 835 /* check for CAN netdev not using header_ops - see gw_rcv() */ 857 836 if (gwj->dst.dev->type != ARPHRD_CAN || gwj->dst.dev->header_ops) 858 837 goto put_src_dst_out; 838 + 839 + gwj->limit_hops = limhops; 859 840 860 841 ASSERT_RTNL(); 861 842 ··· 890 867 } 891 868 } 892 869 893 - static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh) 870 + static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh) 894 871 { 895 872 struct cgw_job *gwj = NULL; 896 873 struct hlist_node *nx; 897 874 struct rtcanmsg *r; 898 875 struct cf_mod mod; 899 876 struct can_can_gw ccgw; 877 + u8 limhops = 0; 900 878 int err = 0; 901 879 902 880 if (!capable(CAP_NET_ADMIN)) ··· 914 890 if (r->gwtype != CGW_TYPE_CAN_CAN) 915 891 return -EINVAL; 916 892 917 - err = cgw_parse_attr(nlh, &mod, CGW_TYPE_CAN_CAN, &ccgw); 893 + err = cgw_parse_attr(nlh, &mod, CGW_TYPE_CAN_CAN, &ccgw, &limhops); 918 894 if (err < 0) 919 895 return err; 920 896 ··· 932 908 hlist_for_each_entry_safe(gwj, nx, &cgw_list, list) { 933 909 934 910 if (gwj->flags != r->flags) 911 + continue; 912 + 913 + if (gwj->limit_hops != limhops) 935 914 continue; 936 915 937 916 if (memcmp(&gwj->mod, &mod, sizeof(mod)))