> +static int ipc_wwan_add_vlan(struct iosm_wwan *ipc_wwan, u16 vid)
> +{
> +     if (vid >= 512 || !ipc_wwan->vlan_devs)
> +             return -EINVAL;
> +
> +     if (vid == WWAN_ROOT_VLAN_TAG)
> +             return 0;
> +
> +     mutex_lock(&ipc_wwan->if_mutex);
> +
> +     /* get channel id */
> +     ipc_wwan->vlan_devs[ipc_wwan->vlan_devs_nr].ch_id =
> +             imem_sys_wwan_open(ipc_wwan->ops_instance, vid);
> +
> +     if (ipc_wwan->vlan_devs[ipc_wwan->vlan_devs_nr].ch_id < 0) {
> +             dev_err(ipc_wwan->dev,
> +                     "cannot connect wwan0 & id %d to the IPC mem layer",
> +                     vid);

Since this is a network interface, you should be using netdev_err(),
netdev_dbg() etc.

> +static int ipc_wwan_open(struct net_device *netdev)
> +{
> +     /* Octets in one ethernet addr */
> +     if (netdev->addr_len < ETH_ALEN) {
> +             pr_err("cannot build the Ethernet address for \"%s\"",
> +                    netdev->name);

checkpatch should of warned about pr_err().

Also, it seems odd you have got as far as open() without a MAC
address. You normally sort this out in probe().

> +int ipc_wwan_receive(struct iosm_wwan *ipc_wwan, struct sk_buff *skb_arg,
> +                  bool dss)
> +{
> +     struct sk_buff *skb = skb_arg;
> +     struct ethhdr *eth = (struct ethhdr *)skb->data;
> +     u16 tag;

Reverse christmas tree.

> +
> +     if (unlikely(!eth)) {
> +             dev_err(ipc_wwan->dev, "ethernet header info error");
> +             dev_kfree_skb(skb);
> +             return -1;
> +     }
> +
> +     ether_addr_copy(eth->h_dest, ipc_wwan->netdev->dev_addr);
> +     ether_addr_copy(eth->h_source, ipc_wwan->netdev->dev_addr);
> +     eth->h_source[ETH_ALEN - 1] ^= 0x01; /* src is us xor 1 */

You are receiving frames without a valid Ethernet header?

> +     /* set the ethernet payload type: ipv4 or ipv6 or Dummy type
> +      * for 802.3 frames
> +      */
> +     eth->h_proto = htons(ETH_P_802_3);

And without a valid ether type?

> +     if (!dss) {
> +             if ((skb->data[ETH_HLEN] & 0xF0) == 0x40)
> +                     eth->h_proto = htons(ETH_P_IP);
> +             else if ((skb->data[ETH_HLEN] & 0xF0) == 0x60)
> +                     eth->h_proto = htons(ETH_P_IPV6);
> +     }

Is this really looking at the first byte after the Ethernet header? If
it finds a 4 it must be IPv4 and a 6 means IPv6?

> +/* Transmit a packet (called by the kernel) */
> +static int ipc_wwan_transmit(struct sk_buff *skb, struct net_device *netdev)
> +{
> +     struct iosm_wwan *ipc_wwan = netdev_priv(netdev);
> +     bool is_ip = false;
> +     int ret = -EINVAL;
> +     int header_size;
> +     int idx = 0;
> +     u16 tag = 0;
> +
> +     vlan_get_tag(skb, &tag);
> +
> +     /* If the SKB is of WWAN root device then don't send it to device.
> +      * Free the SKB and then return.
> +      */
> +     if (unlikely(tag == WWAN_ROOT_VLAN_TAG))
> +             goto exit;
> +
> +     /* Discard the Ethernet header or VLAN Ethernet header depending
> +      * on the protocol.
> +      */

O.K. I have to ask. If this thing does not use an Ethernet header, why
are you writing an Ethernet driver? I assume you also don't use ARP?

It seems a driver more like slip, plip, hdlc, etc would be more
appropriate.

> +static int ipc_wwan_change_mtu(struct net_device *dev, int new_mtu)
> +{
> +     struct iosm_wwan *ipc_wwan = netdev_priv(dev);
> +     unsigned long flags = 0;
> +
> +     if (unlikely(new_mtu < IPC_MEM_MIN_MTU_SIZE ||
> +                  new_mtu > IPC_MEM_MAX_MTU_SIZE)) {

If you set netdev->min_mtu and max_mtu, the core will do this for you.

> +             dev_err(ipc_wwan->dev, "mtu %d out of range %d..%d", new_mtu,
> +                     IPC_MEM_MIN_MTU_SIZE, IPC_MEM_MAX_MTU_SIZE);
> +             return -EINVAL;
> +     }
> +
> +     spin_lock_irqsave(&ipc_wwan->lock, flags);
> +     dev->mtu = new_mtu;
> +     spin_unlock_irqrestore(&ipc_wwan->lock, flags);
> +     return 0;
> +}
> +
> +static int ipc_wwan_change_mac_addr(struct net_device *dev, void *sock_addr)
> +{
> +     struct iosm_wwan *ipc_wwan = netdev_priv(dev);
> +     struct sockaddr *addr = sock_addr;
> +     unsigned long flags = 0;
> +     int result = 0;
> +     u8 *sock_data;
> +
> +     sock_data = (u8 *)addr->sa_data;
> +
> +     spin_lock_irqsave(&ipc_wwan->lock, flags);
> +
> +     if (is_zero_ether_addr(sock_data)) {
> +             dev->addr_len = 1;
> +             memset(dev->dev_addr, 0, 6);
> +             goto exit;
> +     }

It appears you don't have an Ethernet header on the frames. So why do
you need a MAC address?

> +static int ipc_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
> +{
> +     if (cmd != SIOCSIFHWADDR ||
> +         !access_ok((void __user *)ifr, sizeof(struct ifreq)) ||
> +         dev->addr_len > sizeof(struct sockaddr))
> +             return -EINVAL;
> +
> +     return ipc_wwan_change_mac_addr(dev, &ifr->ifr_hwaddr);
> +}

Why not use ndo_set_mac_address() and let the core handle this ioctl?

    Andrew

Reply via email to