Damn_intuition 发表于 2012-11-22 02:15:44

树莓派远程连接不上的一些日志。求大拿分析。

突然出现这个错误,这是重启后在messages中查看到的。

之前的日志没有异常,
出现一下信息后的pi处于无法连接状态。

有没有人能分析下原因嗯。

Nov 22 00:26:47 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to read register index 0x00000114
Nov 22 01:12:16 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to read register index 0x00000114
Nov 22 01:56:39 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to read register index 0x00000114
Nov 22 01:56:44 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to write register index 0x00000114
Nov 22 01:56:49 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to read register index 0x00000114
Nov 22 01:56:54 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to read register index 0x00000118
Nov 22 01:56:59 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to read register index 0x00000114
Nov 22 01:57:04 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to write register index 0x00000114
Nov 22 01:57:09 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to read register index 0x00000114
Nov 22 01:57:14 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to read register index 0x00000118
Nov 22 01:57:21 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to read register index 0x00000114
Nov 22 01:57:26 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to write register index 0x00000114
Nov 22 01:57:31 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to read register index 0x00000114
Nov 22 01:57:36 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to read register index 0x00000118
Nov 22 01:57:41 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to read register index 0x00000114
Nov 22 01:57:46 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to write register index 0x00000114
Nov 22 01:57:51 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to read register index 0x00000114
Nov 22 01:57:56 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to read register index 0x00000118
Nov 22 01:58:01 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to write register index 0x00000014
Nov 22 01:58:01 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to write HW_CFG_LRST_ bit in HW_CFG register, ret = -110
Nov 22 01:58:07 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to write register index 0x00000014
Nov 22 01:58:07 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to write HW_CFG_LRST_ bit in HW_CFG register, ret = -110
Nov 22 01:58:13 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to write register index 0x00000014
Nov 22 01:58:13 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to write HW_CFG_LRST_ bit in HW_CFG register, ret = -110
Nov 22 01:58:19 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to write register index 0x00000014
Nov 22 01:58:19 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to write HW_CFG_LRST_ bit in HW_CFG register, ret = -110
Nov 22 01:58:25 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to write register index 0x00000014
Nov 22 01:58:25 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to write HW_CFG_LRST_ bit in HW_CFG register, ret = -110
Nov 22 01:58:31 raspberrypi kernel: smsc95xx 1-1.1:1.0: eth0: Failed to write register index 0x00000014

Damn_intuition 发表于 2012-11-22 10:02:57

找到个相关信息但是我的设备不是这个设备。
Dell
Dell U2410 Monitor Built-in 4 Port Hub - Shows up as a pair with 0424:2514 and 0424:2640. Standard Microsystems Corp. USB 2.0 Hub. When connecting some devices it kills the Ethernet with "smsc95xx 1-1.1:1.0: eth0: Failed to read register index 0x0000011X" errors. It did work for a keyboard and webcam. Bluetooth that works connected directly to the Pi triggers the error.

Damn_intuition 发表于 2012-11-22 11:09:01

自己挖坑自己埋。~~~

找到网卡的源码,然后发现这个网卡是用的usb总线的。

static int smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data)
{
        u32 *buf = kmalloc(4, GFP_KERNEL);
        int ret;

        BUG_ON(!dev);

        if (!buf)
                return -ENOMEM;

        ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
                USB_VENDOR_REQUEST_READ_REGISTER,
                USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                00, index, buf, 4, USB_CTRL_GET_TIMEOUT);

        if (unlikely(ret < 0))
                netdev_warn(dev->net, "Failed to read register index 0x%08x\n", index);

        le32_to_cpus(buf);
        *data = *buf;
        kfree(buf);

        return ret;
}

Damn_intuition 发表于 2012-11-22 11:32:09

编辑不了帖子了,只好回复了。
static int smsc95xx_reset(struct usbnet *dev)
{
        struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data);
        struct net_device *netdev = dev->net;
        u32 read_buf, write_buf, burst_cap;
        int ret = 0, timeout;

        netif_dbg(dev, ifup, dev->net, "entering smsc95xx_reset\n");

        write_buf = HW_CFG_LRST_;
        ret = smsc95xx_write_reg(dev, HW_CFG, write_buf);
        if (ret < 0) {
                netdev_warn(dev->net, "Failed to write HW_CFG_LRST_ bit in HW_CFG register, ret = %d\n", ret); //问题就处在这个地方
                return ret;
略~~
将request, requesttype, value, index, size加工成usb_ctrlrequest,然后调用usb_internal_control_msg()

dev                     参数dev指向目标设备的usb_device数据结构
pipe                  pipe是个32位无符号整数,其最高两位表示传输的类型(实时/中断/控制/批量),其余各位包括对方的端口号以及设备号,以及设备是否为全速(或者低度)。
requesttype             requesttype其最高位表示传输的方向,最低5位则表明传输终极对象的类别(设备/接口/端口/其他)
index, request, value   index则指明具体的单元,这就是终极的操作对象。针对这个操作对象,request说明了需要进行的具体操作,而value则是参数
data, size            如果有更多的数据需要传递(读/写),则通过缓冲区data进行,其大小为size。 这些都是从用户空间传下来的参数,而传输的目的正是要把这些信息发送给目标设备
timeout               参数timeout表示愿意睡眠等待传输完成的时间
------------------------------------------------------
int usb_control_msg(
    struct usb_device   *dev, unsigned int   pipe,
    __u8 -request, __u8 requesttype, __u16   value,   
    __u16 index,   void *data,       __u16   size,
    int   timeout)
{
    struct usb_ctrlrequest *dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
    int ret;
    if (!dr)
      return -ENOMEM;
    dr->bRequestType= requesttype;
    dr->bRequest = request;
    dr->wValue = cpu_to_le16p(&value);
    dr->wIndex = cpu_to_le16p(&index);
    dr->wLength = cpu_to_le16p(&size);
    ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout);
    kfree(dr);
    return ret;
}static int usb_internal_control_msg(
                  struct usb_device      *usb_dev,
                  unsigned int             pipe,
                  struct usb_ctrlrequest   *cmd,
                  void *data, int len, int timeout)
{
    struct urb *urb;
    int retv;
    int length;
    urb = usb_alloc_urb(0, GFP_NOIO);
    if (!urb)
      return -ENOMEM;

使用参数填充urb,并给urb安插一个回调函数usb_api_blocking_completion(),底层在处理完urb后将会调用该回调函数
|------------------------------------------------------------------------|
|   usb_fill_control_urb( urb,   -usb_dev,   pipe,                     |
|                         (unsigned char *) -cmd,                        |
|                         data,   len,       usb_api_blocking_completion,|
|                         NULL);                                       |
|------------------------------------------------------------------------|

设置好urb以后,通过usb_start_wait_urb()“递交”这个urb数据结构,并等待交互的完成
|-------------------------------------------------------|
|   retv = usb_start_wait_urb(urb, timeout, &length);   |
|-------------------------------------------------------|
    if (retv < 0)
      return retv;
    else
      return length;
}

注:
1.   根Hub最终将通过对urb进行排队

2.   根Hub将通过如下路径回调函数usb_api_blocking_completion()
    usb_start_wait_urb()
    --> usb_submit_urb()
    --> usb_hcd_submit_urb()
    --> rh_urb_enqueue()
    --> rh_call_control()
    --> usb_hcd_giveback_urb()
    --> usb_api_blocking_completion()   

Damn_intuition 发表于 2012-11-22 11:34:42

static int usb_start_wait_urb( struct urb *urb,
                               int      timeout,
                               int      *actual_length)
{
    struct completion done;
    unsigned long expire;
    int status;
    init_completion(&done);
    urb->context = &done;
    urb->actual_length = 0;

将加工好的urb递交给主控制器排队 //问题在这。:@
|---------------------------------------------|
|   status = usb_submit_urb(urb, GFP_NOIO);   |
|---------------------------------------------|

    if (unlikely(status))
      goto out;
    expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT;
    if (!wait_for_completion_timeout(&done, expire)) {
      dev_dbg(&urb->dev->dev,
            "%s timed out on ep%d%s len=%d/%d\n",
            current->comm,
            usb_pipeendpoint(urb->pipe),
            usb_pipein(urb->pipe) ? "in" : "out",
            urb->actual_length,
            urb->transfer_buffer_length);

通过urb获取有效数据后,urb的使命就完成了
|------------------------------|
|       usb_kill_urb(urb);   |
|------------------------------|
      status = urb->status == -ENOENT ? -ETIMEDOUT : urb->status;   
    } else
      status = urb->status;
out:
    if (actual_length)         
      *actual_length = urb->actual_length;
    usb_free_urb(urb);
    return status;
}

Damn_intuition 发表于 2012-11-22 11:36:02

最后到了最关键的了

错误代码:
-ENOMEM      内存不足
-ENODEV      没有设备可用
-EPIPE         端点停止
-EAGAIN      排队等候同步传输的太多
-EFBIG         请求ISO frame的太多
-EINVAL      无效的中断间隔

函数usb_submit_urb递交URB后,urb->status为-EINPROGRESS.
--------------------------------------------------------
int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
{
    int            pipe, temp, max;
    struct usb_device    *dev;
    int            is_out;

    if (!urb || urb->hcpriv || !urb->complete)
      return -EINVAL;
    if (!(dev = urb->dev) ||
      (dev->state < USB_STATE_DEFAULT) ||
      (!dev->bus) || (dev->devnum <= 0))
      return -ENODEV;
    if (dev->bus->controller->power.power_state.event != PM_EVENT_ON
            || dev->state == USB_STATE_SUSPENDED)
      return -EHOSTUNREACH;

    urb->status = -EINPROGRESS;
    urb->actual_length = 0;
    pipe = urb->pipe;
    temp = usb_pipetype(pipe);
    is_out = usb_pipeout(pipe);

    if (!usb_pipecontrol(pipe) && dev->state < USB_STATE_CONFIGURED)
      return -ENODEV;

    //获取usb设备dev所能传输的数据包的最大值(单位是字节)
    max = usb_maxpacket(dev, pipe, is_out);
    if (max <= 0) {
      dev_dbg(&dev->dev,
            "bogus endpoint ep%d%s in %s (bad maxpacket %d)\n",
            usb_pipeendpoint(pipe), is_out ? "out" : "in",
            __FUNCTION__, max);
      return -EMSGSIZE;
    }


处理“负责实时传输的urb”
|---------------------------------------------------------|
|    if (temp == PIPE_ISOCHRONOUS) {                      |
|      int    n, len;                                 |
|      if (dev->speed == USB_SPEED_HIGH) {            |
|            int    mult = 1 + ((max >> 11) & 0x03);      |
|            max &= 0x07ff;                               |
|            max *= mult;                                 |
|      }                                                |
|      if (urb->number_of_packets <= 0)               |
|            return -EINVAL;                              |
|      for (n = 0; n < urb->number_of_packets; n++) {   |
|            len = urb->iso_frame_desc.length;         |
|            if (len < 0 || len > max)                  |
|                return -EMSGSIZE;                        |
|            urb->iso_frame_desc.status = -EXDEV;      |
|            urb->iso_frame_desc.actual_length = 0;    |
|      }                                                |
|    }                                                    |
|---------------------------------------------------------|

    if (urb->transfer_buffer_length < 0)
      return -EMSGSIZE;


--------------------------------------------------------
#ifdef DEBUG
    {
    unsigned int    orig_flags = urb->transfer_flags;
    unsigned int    allowed;
    allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |
            URB_NO_INTERRUPT);
    switch (temp) {
    case PIPE_BULK:
      if (is_out)
            allowed |= URB_ZERO_PACKET;
    case PIPE_CONTROL:
      allowed |= URB_NO_FSBR;   
    default:            
      if (!is_out)
            allowed |= URB_SHORT_NOT_OK;
      break;
    case PIPE_ISOCHRONOUS:
      allowed |= URB_ISO_ASAP;
      break;
    }
    urb->transfer_flags &= allowed;
    if (urb->transfer_flags != orig_flags) {
      err("BOGUS urb flags, %x --> %x",
            orig_flags, urb->transfer_flags);
      return -EINVAL;
    }
    }
#endif
--------------------------------------------------------


设置urb的interval域
********************************************************
    switch (temp) {
    case PIPE_ISOCHRONOUS:
    case PIPE_INTERRUPT:
      if (urb->interval <= 0)
            return -EINVAL;
      switch (dev->speed) {
      case USB_SPEED_HIGH:   
            if (urb->interval > (1024 * 8))
                urb->interval = 1024 * 8;
            temp = 1024 * 8;
            break;
      case USB_SPEED_FULL:   
      case USB_SPEED_LOW:
            if (temp == PIPE_INTERRUPT) {
                if (urb->interval > 255)
                  return -EINVAL;
                temp = 128;
            } else {
                if (urb->interval > 1024)
                  urb->interval = 1024;
                temp = 1024;
            }
            break;
      default:
            return -EINVAL;
      }
      while (temp > urb->interval)
            temp >>= 1;
      urb->interval = temp;
    }
********************************************************


    return usb_hcd_submit_urb(urb, mem_flags);
}

gaoshine 发表于 2012-11-22 17:53:01

一头雾水! 楼主是用RJ45口还是有插了一个无线网卡?

gaoshine 发表于 2012-11-22 18:00:22

google了一下,你看看是不是这个供电干扰问题,您把给raspi供电 和 路由器供电分开试试,或者换个适配器。
原文参考:http://www.raspberrypi.org/phpBB3/viewtopic.php?t=11971&p=129570

Damn_intuition 发表于 2012-11-22 21:06:26

本帖最后由 Damn_intuition 于 2012-11-22 21:13 编辑

gaoshine 发表于 2012-11-22 18:00 static/image/common/back.gif
google了一下,你看看是不是这个供电干扰问题,您把给raspi供电 和 路由器供电分开试试,或者换个适配器。
...

谢谢,我看了下电路和源码,根据猜测是因为usb设备出问题导致的。

因为现在我找不到0x000000那个错误码(手里没有完整的源码),错误码的值定义还不明确。


貌似是因为设备的一些电路因为插排产生电子干扰。产生了一些回路什么的。。。
页: [1]
查看完整版本: 树莓派远程连接不上的一些日志。求大拿分析。