Pages - Menu

Showing posts with label intel. Show all posts
Showing posts with label intel. Show all posts

Thursday, August 29, 2013

finding the netdev_priv struct

In addition to the net_device struct within the kernel, network drivers also have their own private or device-specific struct which stores stats unique to the individual hardware.

The name of the struct varies for each device type, however the location remains the same, right after net_device:

linux-2.6.32-358.14.1.el6.x86_64/include/linux/netdevice.h
/**
 *      netdev_priv - access network device private data
 *      @dev: network device
 *
 * Get network device private data
 */
static inline void *netdev_priv(const struct net_device *dev)
{
        return (char *)dev + ALIGN(sizeof(struct net_device), NETDEV_ALIGN);
}
A search in cscope for netdev_priv will show you many functions within drivers which update the priv structure via pointers, for example this one in e1000_main.c:
struct e1000_adapter *adapter = netdev_priv(netdev);
So, given that we know what the device-specific struct is called, and where the device-specific private struct is, how do you find it and read it?

We'll need the ability to read kernel memory using crash, either run on a live system, or in a vmcore captured with kdump:
crash /usr/lib/debug/lib/modules/2.6.32-358.14.1.el6.x86_64/vmlinux /var/crash/2013-08-26/vmcore
We'll also need the debugging symbols for the driver in question:
crash> mod -s e1000 /usr/lib/debug/lib/modules/2.6.32-358.14.1.el6.x86_64/kernel/drivers/net/e1000/e1000.ko.debug
     MODULE       NAME                 SIZE  OBJECT FILE
ffffffffa01550e0  e1000              170678  /usr/lib/debug/lib/modules/2.6.32-358.14.1.el6.x86_64/kernel/drivers/net/e1000/e1000.ko.debug 
The net command will show you the network devices in the system:
crash> net
   NET_DEVICE     NAME   IP ADDRESS(ES)
ffff88007e76b820  lo     127.0.0.1
ffff8800372c0020  eth0   192.168.1.126
We can then cast net_device against this to see the in-kernel device struct:
crash> net_device 0xffff8800372c0020
struct net_device {
  name = "eth0\000\000\060:03.0\000\000\000",
...
But we want to get after this struct and cast it against the struct in the driver.

We need to know how big net_device is:
crash> struct -o net_device
struct net_device {
...
}
SIZE: 1728
We then find the net address plus the size of net_device:
crash> px 0xffff8800372c0020+1728
$1 = 0xffff8800372c06e0
We can now cast the device-specific private struct against this new address:
crash> e1000_adapter 0xffff8800372c06e0
struct e1000_adapter {
  vlgrp = 0x0,
  mng_vlan_id = 65535,
  bd_number = 0,
  rx_buffer_len = 1522,
...
and we're done!

Monday, November 10, 2008

Font DPI broken in Intrepid

I upgraded my laptop (a Dell Vostro 1200) to Ubuntu Intrepid, and found my fonts in both GDM and Openbox were 2 sizes larger than expected. This made things look awful, so I started hunting around for a fix.

Fonts should be 96x96 DPI, for this, both the video driver and X need to know how physically large your screen is, in addition to the resolution they're displaying. xdpyinfo | grep dimensions reported the correct screen size in mm I was expecting, but cat /var/log/Xorg.0.log | grep DPI reported that the intel(0) driver was seeing a DPI of 95x153!!!

After browsing Ubuntu's Launchpad and the Arch Linux Wiki for a while, I found it seems to be a bug in the Xorg Intel video driver, specifically that it can't read the resolution information from my laptop's LCD panel properly.

My fix for this was by editing my /etc/X11/xorg.conf file, and adding these lines to the Device and Monitor sections:

Section "Device"
... existing info here...
Option "Monitor-LVDS" "Configured Monitor"
EndSection

Section "Monitor"
... existing info here ...
Identifier "Configured Monitor"
DisplaySize 339 212
EndSection


If you have a different resolution than 1280x800, you can calculate these values with the formula pixels*25.4/dpi and always round down. eg: 1024*25.4/96=270

Apparently if you have a nVidia card, using the nvidia binary driver, these options work:
Section "Device"
... existing info here ...
Option "UseEdidDpi" "false"
Option "DPI" "96 x 96"
EndSection

Others have also reported that starting X with a manual DPI setting can work. You can do this by editing /etc/gdm/gdm.conf and finding this:
command=/usr/X11R6/bin/X -br -audit 0
and adding -dpi 96 on the end, so you get this
command=/usr/X11R6/bin/X -br -audit 0 -dpi 96
However, this did not work for me.

Some people have found that specifying Option "NoDDC" "true" in the Monitor/Device sections of their xorg.conf fixes this too. DDC is a protocol that reads extended information from your monitor that could be important (resolutions, refresh rates) so disabling it isn't really a "fix" as such. I don't recommend disabling DDC, especially if you are using a CRT which could be fried by an incorrect refresh rate.

The fix, either Intel's Monitor-LVDS command, nVidia's UseEdidDpi False, or starting X with a manual DPI, seems to be dependent on which video card and driver you are using. Out of interest, the fbdev driver (framebuffer, displays usplash and Ctrl+Alt+F1 terminals) would read DPI properly, but was restricted to 1024x786 res only.