diff options
Diffstat (limited to 'drivers')
47 files changed, 766 insertions, 690 deletions
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 00e72b1..b90468a 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -58,8 +58,8 @@ obj-$(CONFIG_STNIC) += stnic.o 8390.o obj-$(CONFIG_FEALNX) += fealnx.o obj-$(CONFIG_TIGON3) += tg3.o obj-$(CONFIG_BNX2) += bnx2.o -spidernet-y += spider_net.o spider_net_ethtool.o sungem_phy.o -obj-$(CONFIG_SPIDER_NET) += spidernet.o +spidernet-y += spider_net.o spider_net_ethtool.o +obj-$(CONFIG_SPIDER_NET) += spidernet.o sungem_phy.o obj-$(CONFIG_TC35815) += tc35815.o obj-$(CONFIG_SKGE) += skge.o obj-$(CONFIG_SKY2) += sky2.o diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index cd0b1dc..1363083 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -90,8 +90,6 @@ static void au1000_tx_timeout(struct net_device *); static int au1000_set_config(struct net_device *dev, struct ifmap *map); static void set_rx_mode(struct net_device *); static struct net_device_stats *au1000_get_stats(struct net_device *); -static inline void update_tx_stats(struct net_device *, u32, u32); -static inline void update_rx_stats(struct net_device *, u32); static void au1000_timer(unsigned long); static int au1000_ioctl(struct net_device *, struct ifreq *, int); static int mdio_read(struct net_device *, int, int); @@ -1825,16 +1823,11 @@ static void __exit au1000_cleanup_module(void) } } - -static inline void -update_tx_stats(struct net_device *dev, u32 status, u32 pkt_len) +static void update_tx_stats(struct net_device *dev, u32 status) { struct au1000_private *aup = (struct au1000_private *) dev->priv; struct net_device_stats *ps = &aup->stats; - ps->tx_packets++; - ps->tx_bytes += pkt_len; - if (status & TX_FRAME_ABORTED) { if (dev->if_port == IF_PORT_100BASEFX) { if (status & (TX_JAB_TIMEOUT | TX_UNDERRUN)) { @@ -1867,7 +1860,7 @@ static void au1000_tx_ack(struct net_device *dev) ptxd = aup->tx_dma_ring[aup->tx_tail]; while (ptxd->buff_stat & TX_T_DONE) { - update_tx_stats(dev, ptxd->status, ptxd->len & 0x3ff); + update_tx_stats(dev, ptxd->status); ptxd->buff_stat &= ~TX_T_DONE; ptxd->len = 0; au_sync(); @@ -1889,6 +1882,7 @@ static void au1000_tx_ack(struct net_device *dev) static int au1000_tx(struct sk_buff *skb, struct net_device *dev) { struct au1000_private *aup = (struct au1000_private *) dev->priv; + struct net_device_stats *ps = &aup->stats; volatile tx_dma_t *ptxd; u32 buff_stat; db_dest_t *pDB; @@ -1908,7 +1902,7 @@ static int au1000_tx(struct sk_buff *skb, struct net_device *dev) return 1; } else if (buff_stat & TX_T_DONE) { - update_tx_stats(dev, ptxd->status, ptxd->len & 0x3ff); + update_tx_stats(dev, ptxd->status); ptxd->len = 0; } @@ -1928,6 +1922,9 @@ static int au1000_tx(struct sk_buff *skb, struct net_device *dev) else ptxd->len = skb->len; + ps->tx_packets++; + ps->tx_bytes += ptxd->len; + ptxd->buff_stat = pDB->dma_addr | TX_DMA_ENABLE; au_sync(); dev_kfree_skb(skb); @@ -1936,7 +1933,6 @@ static int au1000_tx(struct sk_buff *skb, struct net_device *dev) return 0; } - static inline void update_rx_stats(struct net_device *dev, u32 status) { struct au1000_private *aup = (struct au1000_private *) dev->priv; diff --git a/drivers/net/depca.c b/drivers/net/depca.c index 03804cc..0941d40 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -1412,7 +1412,7 @@ static int __init depca_mca_probe(struct device *device) irq = 11; break; default: - printk("%s: mca_probe IRQ error. You should never get here (%d).\n", dev->name, where); + printk("%s: mca_probe IRQ error. You should never get here (%d).\n", mdev->name, where); return -EINVAL; } diff --git a/drivers/net/ixp2000/enp2611.c b/drivers/net/ixp2000/enp2611.c index d82651a..6f7dce8 100644 --- a/drivers/net/ixp2000/enp2611.c +++ b/drivers/net/ixp2000/enp2611.c @@ -16,7 +16,7 @@ #include <linux/etherdevice.h> #include <linux/init.h> #include <linux/moduleparam.h> -#include <asm/arch/uengine.h> +#include <asm/hardware/uengine.h> #include <asm/mach-types.h> #include <asm/io.h> #include "ixpdev.h" diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c index 09f03f4..77f104a 100644 --- a/drivers/net/ixp2000/ixpdev.c +++ b/drivers/net/ixp2000/ixpdev.c @@ -16,7 +16,7 @@ #include <linux/etherdevice.h> #include <linux/init.h> #include <linux/moduleparam.h> -#include <asm/arch/uengine.h> +#include <asm/hardware/uengine.h> #include <asm/mach-types.h> #include <asm/io.h> #include "ixp2400_rx.ucode" diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index a1cb07c..253440a 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -128,6 +128,7 @@ static const struct mii_chip_info { { "SiS 900 Internal MII PHY", 0x001d, 0x8000, LAN }, { "SiS 7014 Physical Layer Solution", 0x0016, 0xf830, LAN }, { "Altimata AC101LF PHY", 0x0022, 0x5520, LAN }, + { "ADM 7001 LAN PHY", 0x002e, 0xcc60, LAN }, { "AMD 79C901 10BASE-T PHY", 0x0000, 0x6B70, LAN }, { "AMD 79C901 HomePNA PHY", 0x0000, 0x6B90, HOME}, { "ICS LAN PHY", 0x0015, 0xF440, LAN }, diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index f08fe6c..36db938 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2478,17 +2478,34 @@ static const struct sky2_stat { { "rx_unicast", GM_RXF_UC_OK }, { "tx_mac_pause", GM_TXF_MPAUSE }, { "rx_mac_pause", GM_RXF_MPAUSE }, - { "collisions", GM_TXF_SNG_COL }, + { "collisions", GM_TXF_COL }, { "late_collision",GM_TXF_LAT_COL }, { "aborted", GM_TXF_ABO_COL }, + { "single_collisions", GM_TXF_SNG_COL }, { "multi_collisions", GM_TXF_MUL_COL }, - { "fifo_underrun", GM_TXE_FIFO_UR }, - { "fifo_overflow", GM_RXE_FIFO_OV }, - { "rx_toolong", GM_RXF_LNG_ERR }, - { "rx_jabber", GM_RXF_JAB_PKT }, + + { "rx_short", GM_RXE_SHT }, { "rx_runt", GM_RXE_FRAG }, + { "rx_64_byte_packets", GM_RXF_64B }, + { "rx_65_to_127_byte_packets", GM_RXF_127B }, + { "rx_128_to_255_byte_packets", GM_RXF_255B }, + { "rx_256_to_511_byte_packets", GM_RXF_511B }, + { "rx_512_to_1023_byte_packets", GM_RXF_1023B }, + { "rx_1024_to_1518_byte_packets", GM_RXF_1518B }, + { "rx_1518_to_max_byte_packets", GM_RXF_MAX_SZ }, { "rx_too_long", GM_RXF_LNG_ERR }, + { "rx_fifo_overflow", GM_RXE_FIFO_OV }, + { "rx_jabber", GM_RXF_JAB_PKT }, { "rx_fcs_error", GM_RXF_FCS_ERR }, + + { "tx_64_byte_packets", GM_TXF_64B }, + { "tx_65_to_127_byte_packets", GM_TXF_127B }, + { "tx_128_to_255_byte_packets", GM_TXF_255B }, + { "tx_256_to_511_byte_packets", GM_TXF_511B }, + { "tx_512_to_1023_byte_packets", GM_TXF_1023B }, + { "tx_1024_to_1518_byte_packets", GM_TXF_1518B }, + { "tx_1519_to_max_byte_packets", GM_TXF_MAX_SZ }, + { "tx_fifo_underrun", GM_TXE_FIFO_UR }, }; static u32 sky2_get_rx_csum(struct net_device *dev) diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index d63cd5a..2838f66 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -1373,23 +1373,23 @@ enum { GM_SMI_CTRL = 0x0080, /* 16 bit r/w SMI Control Register */ GM_SMI_DATA = 0x0084, /* 16 bit r/w SMI Data Register */ GM_PHY_ADDR = 0x0088, /* 16 bit r/w GPHY Address Register */ +/* MIB Counters */ + GM_MIB_CNT_BASE = 0x0100, /* Base Address of MIB Counters */ + GM_MIB_CNT_SIZE = 256, }; -/* MIB Counters */ -#define GM_MIB_CNT_BASE 0x0100 /* Base Address of MIB Counters */ -#define GM_MIB_CNT_SIZE 44 /* Number of MIB Counters */ /* * MIB Counters base address definitions (low word) - * use offset 4 for access to high word (32 bit r/o) */ enum { - GM_RXF_UC_OK = GM_MIB_CNT_BASE + 0, /* Unicast Frames Received OK */ + GM_RXF_UC_OK = GM_MIB_CNT_BASE + 0, /* Unicast Frames Received OK */ GM_RXF_BC_OK = GM_MIB_CNT_BASE + 8, /* Broadcast Frames Received OK */ GM_RXF_MPAUSE = GM_MIB_CNT_BASE + 16, /* Pause MAC Ctrl Frames Received */ GM_RXF_MC_OK = GM_MIB_CNT_BASE + 24, /* Multicast Frames Received OK */ GM_RXF_FCS_ERR = GM_MIB_CNT_BASE + 32, /* Rx Frame Check Seq. Error */ - /* GM_MIB_CNT_BASE + 40: reserved */ + GM_RXO_OK_LO = GM_MIB_CNT_BASE + 48, /* Octets Received OK Low */ GM_RXO_OK_HI = GM_MIB_CNT_BASE + 56, /* Octets Received OK High */ GM_RXO_ERR_LO = GM_MIB_CNT_BASE + 64, /* Octets Received Invalid Low */ @@ -1397,37 +1397,36 @@ enum { GM_RXF_SHT = GM_MIB_CNT_BASE + 80, /* Frames <64 Byte Received OK */ GM_RXE_FRAG = GM_MIB_CNT_BASE + 88, /* Frames <64 Byte Received with FCS Err */ GM_RXF_64B = GM_MIB_CNT_BASE + 96, /* 64 Byte Rx Frame */ - GM_RXF_127B = GM_MIB_CNT_BASE + 104, /* 65-127 Byte Rx Frame */ - GM_RXF_255B = GM_MIB_CNT_BASE + 112, /* 128-255 Byte Rx Frame */ - GM_RXF_511B = GM_MIB_CNT_BASE + 120, /* 256-511 Byte Rx Frame */ - GM_RXF_1023B = GM_MIB_CNT_BASE + 128, /* 512-1023 Byte Rx Frame */ - GM_RXF_1518B = GM_MIB_CNT_BASE + 136, /* 1024-1518 Byte Rx Frame */ - GM_RXF_MAX_SZ = GM_MIB_CNT_BASE + 144, /* 1519-MaxSize Byte Rx Frame */ - GM_RXF_LNG_ERR = GM_MIB_CNT_BASE + 152, /* Rx Frame too Long Error */ - GM_RXF_JAB_PKT = GM_MIB_CNT_BASE + 160, /* Rx Jabber Packet Frame */ - /* GM_MIB_CNT_BASE + 168: reserved */ - GM_RXE_FIFO_OV = GM_MIB_CNT_BASE + 176, /* Rx FIFO overflow Event */ - /* GM_MIB_CNT_BASE + 184: reserved */ - GM_TXF_UC_OK = GM_MIB_CNT_BASE + 192, /* Unicast Frames Xmitted OK */ - GM_TXF_BC_OK = GM_MIB_CNT_BASE + 200, /* Broadcast Frames Xmitted OK */ - GM_TXF_MPAUSE = GM_MIB_CNT_BASE + 208, /* Pause MAC Ctrl Frames Xmitted */ - GM_TXF_MC_OK = GM_MIB_CNT_BASE + 216, /* Multicast Frames Xmitted OK */ - GM_TXO_OK_LO = GM_MIB_CNT_BASE + 224, /* Octets Transmitted OK Low */ - GM_TXO_OK_HI = GM_MIB_CNT_BASE + 232, /* Octets Transmitted OK High */ - GM_TXF_64B = GM_MIB_CNT_BASE + 240, /* 64 Byte Tx Frame */ - GM_TXF_127B = GM_MIB_CNT_BASE + 248, /* 65-127 Byte Tx Frame */ - GM_TXF_255B = GM_MIB_CNT_BASE + 256, /* 128-255 Byte Tx Frame */ - GM_TXF_511B = GM_MIB_CNT_BASE + 264, /* 256-511 Byte Tx Frame */ - GM_TXF_1023B = GM_MIB_CNT_BASE + 272, /* 512-1023 Byte Tx Frame */ - GM_TXF_1518B = GM_MIB_CNT_BASE + 280, /* 1024-1518 Byte Tx Frame */ - GM_TXF_MAX_SZ = GM_MIB_CNT_BASE + 288, /* 1519-MaxSize Byte Tx Frame */ - - GM_TXF_COL = GM_MIB_CNT_BASE + 304, /* Tx Collision */ - GM_TXF_LAT_COL = GM_MIB_CNT_BASE + 312, /* Tx Late Collision */ - GM_TXF_ABO_COL = GM_MIB_CNT_BASE + 320, /* Tx aborted due to Exces. Col. */ - GM_TXF_MUL_COL = GM_MIB_CNT_BASE + 328, /* Tx Multiple Collision */ - GM_TXF_SNG_COL = GM_MIB_CNT_BASE + 336, /* Tx Single Collision */ - GM_TXE_FIFO_UR = GM_MIB_CNT_BASE + 344, /* Tx FIFO Underrun Event */ + GM_RXF_127B = GM_MIB_CNT_BASE + 104,/* 65-127 Byte Rx Frame */ + GM_RXF_255B = GM_MIB_CNT_BASE + 112,/* 128-255 Byte Rx Frame */ + GM_RXF_511B = GM_MIB_CNT_BASE + 120,/* 256-511 Byte Rx Frame */ + GM_RXF_1023B = GM_MIB_CNT_BASE + 128,/* 512-1023 Byte Rx Frame */ + GM_RXF_1518B = GM_MIB_CNT_BASE + 136,/* 1024-1518 Byte Rx Frame */ + GM_RXF_MAX_SZ = GM_MIB_CNT_BASE + 144,/* 1519-MaxSize Byte Rx Frame */ + GM_RXF_LNG_ERR = GM_MIB_CNT_BASE + 152,/* Rx Frame too Long Error */ + GM_RXF_JAB_PKT = GM_MIB_CNT_BASE + 160,/* Rx Jabber Packet Frame */ + + GM_RXE_FIFO_OV = GM_MIB_CNT_BASE + 176,/* Rx FIFO overflow Event */ + GM_TXF_UC_OK = GM_MIB_CNT_BASE + 192,/* Unicast Frames Xmitted OK */ + GM_TXF_BC_OK = GM_MIB_CNT_BASE + 200,/* Broadcast Frames Xmitted OK */ + GM_TXF_MPAUSE = GM_MIB_CNT_BASE + 208,/* Pause MAC Ctrl Frames Xmitted */ + GM_TXF_MC_OK = GM_MIB_CNT_BASE + 216,/* Multicast Frames Xmitted OK */ + GM_TXO_OK_LO = GM_MIB_CNT_BASE + 224,/* Octets Transmitted OK Low */ + GM_TXO_OK_HI = GM_MIB_CNT_BASE + 232,/* Octets Transmitted OK High */ + GM_TXF_64B = GM_MIB_CNT_BASE + 240,/* 64 Byte Tx Frame */ + GM_TXF_127B = GM_MIB_CNT_BASE + 248,/* 65-127 Byte Tx Frame */ + GM_TXF_255B = GM_MIB_CNT_BASE + 256,/* 128-255 Byte Tx Frame */ + GM_TXF_511B = GM_MIB_CNT_BASE + 264,/* 256-511 Byte Tx Frame */ + GM_TXF_1023B = GM_MIB_CNT_BASE + 272,/* 512-1023 Byte Tx Frame */ + GM_TXF_1518B = GM_MIB_CNT_BASE + 280,/* 1024-1518 Byte Tx Frame */ + GM_TXF_MAX_SZ = GM_MIB_CNT_BASE + 288,/* 1519-MaxSize Byte Tx Frame */ + + GM_TXF_COL = GM_MIB_CNT_BASE + 304,/* Tx Collision */ + GM_TXF_LAT_COL = GM_MIB_CNT_BASE + 312,/* Tx Late Collision */ + GM_TXF_ABO_COL = GM_MIB_CNT_BASE + 320,/* Tx aborted due to Exces. Col. */ + GM_TXF_MUL_COL = GM_MIB_CNT_BASE + 328,/* Tx Multiple Collision */ + GM_TXF_SNG_COL = GM_MIB_CNT_BASE + 336,/* Tx Single Collision */ + GM_TXE_FIFO_UR = GM_MIB_CNT_BASE + 344,/* Tx FIFO Underrun Event */ }; /* GMAC Bit Definitions */ diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 6299e18..e3dd144 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -1327,11 +1327,11 @@ static void de_clean_rings (struct de_private *de) struct sk_buff *skb = de->tx_skb[i].skb; if ((skb) && (skb != DE_DUMMY_SKB)) { if (skb != DE_SETUP_SKB) { - dev_kfree_skb(skb); de->net_stats.tx_dropped++; pci_unmap_single(de->pdev, de->tx_skb[i].mapping, skb->len, PCI_DMA_TODEVICE); + dev_kfree_skb(skb); } else { pci_unmap_single(de->pdev, de->tx_skb[i].mapping, diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c index 1084525..d121644 100644 --- a/drivers/parport/parport_serial.c +++ b/drivers/parport/parport_serial.c @@ -31,14 +31,8 @@ enum parport_pc_pci_cards { netmos_9xx5_combo, netmos_9855, avlab_1s1p, - avlab_1s1p_650, - avlab_1s1p_850, avlab_1s2p, - avlab_1s2p_650, - avlab_1s2p_850, avlab_2s1p, - avlab_2s1p_650, - avlab_2s1p_850, siig_1s1p_10x, siig_2s1p_10x, siig_2p1s_20x, @@ -85,14 +79,8 @@ static struct parport_pc_pci cards[] __devinitdata = { /* netmos_9xx5_combo */ { 1, { { 2, -1 }, }, netmos_parallel_init }, /* netmos_9855 */ { 1, { { 0, -1 }, }, netmos_parallel_init }, /* avlab_1s1p */ { 1, { { 1, 2}, } }, - /* avlab_1s1p_650 */ { 1, { { 1, 2}, } }, - /* avlab_1s1p_850 */ { 1, { { 1, 2}, } }, /* avlab_1s2p */ { 2, { { 1, 2}, { 3, 4 },} }, - /* avlab_1s2p_650 */ { 2, { { 1, 2}, { 3, 4 },} }, - /* avlab_1s2p_850 */ { 2, { { 1, 2}, { 3, 4 },} }, /* avlab_2s1p */ { 1, { { 2, 3}, } }, - /* avlab_2s1p_650 */ { 1, { { 2, 3}, } }, - /* avlab_2s1p_850 */ { 1, { { 2, 3}, } }, /* siig_1s1p_10x */ { 1, { { 3, 4 }, } }, /* siig_2s1p_10x */ { 1, { { 4, 5 }, } }, /* siig_2p1s_20x */ { 2, { { 1, 2 }, { 3, 4 }, } }, @@ -119,15 +107,24 @@ static struct pci_device_id parport_serial_pci_tbl[] = { { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855, PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 }, /* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/ - { 0x14db, 0x2110, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p}, - { 0x14db, 0x2111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p_650}, - { 0x14db, 0x2112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p_850}, - { 0x14db, 0x2140, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p}, - { 0x14db, 0x2141, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p_650}, - { 0x14db, 0x2142, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p_850}, - { 0x14db, 0x2160, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p}, - { 0x14db, 0x2161, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p_650}, - { 0x14db, 0x2162, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p_850}, + { PCI_VENDOR_ID_AFAVLAB, 0x2110, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p }, + { PCI_VENDOR_ID_AFAVLAB, 0x2111, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p }, + { PCI_VENDOR_ID_AFAVLAB, 0x2112, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p }, + { PCI_VENDOR_ID_AFAVLAB, 0x2140, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p }, + { PCI_VENDOR_ID_AFAVLAB, 0x2141, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p }, + { PCI_VENDOR_ID_AFAVLAB, 0x2142, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p }, + { PCI_VENDOR_ID_AFAVLAB, 0x2160, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p }, + { PCI_VENDOR_ID_AFAVLAB, 0x2161, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p }, + { PCI_VENDOR_ID_AFAVLAB, 0x2162, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650, @@ -201,54 +198,18 @@ static struct pciserial_board pci_parport_serial_boards[] __devinitdata = { .base_baud = 115200, .uart_offset = 8, }, - [avlab_1s1p_650] = { /* nt */ - .flags = FL_BASE0 | FL_BASE_BARS, - .num_ports = 1, - .base_baud = 115200, - .uart_offset = 8, - }, - [avlab_1s1p_850] = { /* nt */ - .flags = FL_BASE0 | FL_BASE_BARS, - .num_ports = 1, - .base_baud = 115200, - .uart_offset = 8, - }, [avlab_1s2p] = { /* n/t */ .flags = FL_BASE0 | FL_BASE_BARS, .num_ports = 1, .base_baud = 115200, .uart_offset = 8, }, - [avlab_1s2p_650] = { /* nt */ - .flags = FL_BASE0 | FL_BASE_BARS, - .num_ports = 1, - .base_baud = 115200, - .uart_offset = 8, - }, - [avlab_1s2p_850] = { /* nt */ - .flags = FL_BASE0 | FL_BASE_BARS, - .num_ports = 1, - .base_baud = 115200, - .uart_offset = 8, - }, [avlab_2s1p] = { /* n/t */ .flags = FL_BASE0 | FL_BASE_BARS, .num_ports = 2, .base_baud = 115200, .uart_offset = 8, }, - [avlab_2s1p_650] = { /* nt */ - .flags = FL_BASE0 | FL_BASE_BARS, - .num_ports = 2, - .base_baud = 115200, - .uart_offset = 8, - }, - [avlab_2s1p_850] = { /* nt */ - .flags = FL_BASE0 | FL_BASE_BARS, - .num_ports = 2, - .base_baud = 115200, - .uart_offset = 8, - }, [siig_1s1p_10x] = { .flags = FL_BASE2, .num_ports = 1, diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index dba7f7f..021cd5d 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -1364,7 +1364,7 @@ qeth_wait_for_buffer(struct qeth_channel *channel) static void qeth_clear_cmd_buffers(struct qeth_channel *channel) { - int cnt = 0; + int cnt; for (cnt=0; cnt < QETH_CMD_BUFFER_NO; cnt++) qeth_release_buffer(channel,&channel->iob[cnt]); @@ -2814,11 +2814,11 @@ qeth_handle_send_error(struct qeth_card *card, QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card)); return QETH_SEND_ERROR_LINK_FAILURE; case 3: + default: QETH_DBF_TEXT(trace, 1, "SIGAcc3"); QETH_DBF_TEXT_(trace,1,"%s",CARD_BUS_ID(card)); return QETH_SEND_ERROR_KICK_IT; } - return QETH_SEND_ERROR_LINK_FAILURE; } void @@ -3865,6 +3865,7 @@ qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb) if ((hdr_mac == QETH_TR_MAC_NC) || (hdr_mac == QETH_TR_MAC_C)) return RTN_MULTICAST; + break; /* eth or so multicast? */ default: if ((hdr_mac == QETH_ETH_MAC_V4) || @@ -4419,6 +4420,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) int elements_needed = 0; enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; struct qeth_eddp_context *ctx = NULL; + int tx_bytes = skb->len; int rc; QETH_DBF_TEXT(trace, 6, "sendpkt"); @@ -4499,7 +4501,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) elements_needed, ctx); if (!rc){ card->stats.tx_packets++; - card->stats.tx_bytes += skb->len; + card->stats.tx_bytes += tx_bytes; #ifdef CONFIG_QETH_PERF_STATS if (skb_shinfo(skb)->tso_size && !(large_send == QETH_LARGE_SEND_NO)) { @@ -4585,38 +4587,11 @@ qeth_mdio_read(struct net_device *dev, int phy_id, int regnum) case MII_NCONFIG: /* network interface config */ break; default: - rc = 0; break; } return rc; } -static void -qeth_mdio_write(struct net_device *dev, int phy_id, int regnum, int value) -{ - switch(regnum){ - case MII_BMCR: /* Basic mode control register */ - case MII_BMSR: /* Basic mode status register */ - case MII_PHYSID1: /* PHYS ID 1 */ - case MII_PHYSID2: /* PHYS ID 2 */ - case MII_ADVERTISE: /* Advertisement control reg */ - case MII_LPA: /* Link partner ability reg */ - case MII_EXPANSION: /* Expansion register */ - case MII_DCOUNTER: /* disconnect counter */ - case MII_FCSCOUNTER: /* false carrier counter */ - case MII_NWAYTEST: /* N-way auto-neg test register */ - case MII_RERRCOUNTER: /* rx error counter */ - case MII_SREVISION: /* silicon revision */ - case MII_RESV1: /* reserved 1 */ - case MII_LBRERROR: /* loopback, rx, bypass error */ - case MII_PHYADDR: /* physical address */ - case MII_RESV2: /* reserved 2 */ - case MII_TPISTATUS: /* TPI status for 10mbps */ - case MII_NCONFIG: /* network interface config */ - default: - break; - } -} static inline const char * qeth_arp_get_error_cause(int *rc) @@ -5236,21 +5211,6 @@ qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) mii_data->val_out = qeth_mdio_read(dev,mii_data->phy_id, mii_data->reg_num); break; - case SIOCSMIIREG: - rc = -EOPNOTSUPP; - break; - /* TODO: remove return if qeth_mdio_write does something */ - if (!capable(CAP_NET_ADMIN)){ - rc = -EPERM; - break; - } - mii_data = if_mii(rq); - if (mii_data->phy_id != 0) - rc = -EINVAL; - else - qeth_mdio_write(dev, mii_data->phy_id, mii_data->reg_num, - mii_data->val_in); - break; default: rc = -EOPNOTSUPP; } @@ -6900,7 +6860,7 @@ qeth_send_setassparms(struct qeth_card *card, struct qeth_cmd_buffer *iob, cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); if (len <= sizeof(__u32)) cmd->data.setassparms.data.flags_32bit = (__u32) data; - else if (len > sizeof(__u32)) + else /* (len > sizeof(__u32)) */ memcpy(&cmd->data.setassparms.data, (void *) data, len); rc = qeth_send_ipa_cmd(card, iob, reply_cb, reply_param); @@ -7379,11 +7339,6 @@ qeth_setrouting_v6(struct qeth_card *card) qeth_correct_routing_type(card, &card->options.route6.type, QETH_PROT_IPV6); - if ((card->options.route6.type == NO_ROUTER) || - ((card->info.type == QETH_CARD_TYPE_OSAE) && - (card->options.route6.type == MULTICAST_ROUTER) && - !qeth_is_supported6(card,IPA_OSA_MC_ROUTER))) - return 0; rc = qeth_send_setrouting(card, card->options.route6.type, QETH_PROT_IPV6); if (rc) { diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c index 3c6339d..360d782 100644 --- a/drivers/s390/net/qeth_proc.c +++ b/drivers/s390/net/qeth_proc.c @@ -74,7 +74,7 @@ qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset) static inline const char * qeth_get_router_str(struct qeth_card *card, int ipv) { - int routing_type = 0; + enum qeth_routing_types routing_type = NO_ROUTER; if (ipv == 4) { routing_type = card->options.route4.type; @@ -86,26 +86,26 @@ qeth_get_router_str(struct qeth_card *card, int ipv) #endif /* CONFIG_QETH_IPV6 */ } - if (routing_type == PRIMARY_ROUTER) + switch (routing_type){ + case PRIMARY_ROUTER: return "pri"; - else if (routing_type == SECONDARY_ROUTER) + case SECONDARY_ROUTER: return "sec"; - else if (routing_type == MULTICAST_ROUTER) { + case MULTICAST_ROUTER: if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO) return "mc+"; return "mc"; - } else if (routing_type == PRIMARY_CONNECTOR) { + case PRIMARY_CONNECTOR: if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO) return "p+c"; return "p.c"; - } else if (routing_type == SECONDARY_CONNECTOR) { + case SECONDARY_CONNECTOR: if (card->info.broadcast_capable == QETH_BROADCAST_WITHOUT_ECHO) return "s+c"; return "s.c"; - } else if (routing_type == NO_ROUTER) + default: /* NO_ROUTER */ return "no"; - else - return "unk"; + } } static int @@ -192,27 +192,27 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it) CARD_DDEV_ID(card), QETH_CARD_IFNAME(card) ); - seq_printf(s, " Skb's/buffers received : %li/%i\n" - " Skb's/buffers sent : %li/%i\n\n", + seq_printf(s, " Skb's/buffers received : %lu/%u\n" + " Skb's/buffers sent : %lu/%u\n\n", card->stats.rx_packets, card->perf_stats.bufs_rec, card->stats.tx_packets, card->perf_stats.bufs_sent ); - seq_printf(s, " Skb's/buffers sent without packing : %li/%i\n" - " Skb's/buffers sent with packing : %i/%i\n\n", + seq_printf(s, " Skb's/buffers sent without packing : %lu/%u\n" + " Skb's/buffers sent with packing : %u/%u\n\n", card->stats.tx_packets - card->perf_stats.skbs_sent_pack, card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack, card->perf_stats.skbs_sent_pack, card->perf_stats.bufs_sent_pack ); - seq_printf(s, " Skbs sent in SG mode : %i\n" - " Skb fragments sent in SG mode : %i\n\n", + seq_printf(s, " Skbs sent in SG mode : %u\n" + " Skb fragments sent in SG mode : %u\n\n", card->perf_stats.sg_skbs_sent, card->perf_stats.sg_frags_sent); - seq_printf(s, " large_send tx (in Kbytes) : %i\n" - " large_send count : %i\n\n", + seq_printf(s, " large_send tx (in Kbytes) : %u\n" + " large_send count : %u\n\n", card->perf_stats.large_send_bytes >> 10, card->perf_stats.large_send_cnt); - seq_printf(s, " Packing state changes no pkg.->packing : %i/%i\n" + seq_printf(s, " Packing state changes no pkg.->packing : %u/%u\n" " Watermarks L/H : %i/%i\n" " Current buffer usage (outbound q's) : " "%i/%i/%i/%i\n\n", @@ -229,16 +229,16 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it) atomic_read(&card->qdio.out_qs[3]->used_buffers) : 0 ); - seq_printf(s, " Inbound handler time (in us) : %i\n" - " Inbound handler count : %i\n" - " Inbound do_QDIO time (in us) : %i\n" - " Inbound do_QDIO count : %i\n\n" - " Outbound handler time (in us) : %i\n" - " Outbound handler count : %i\n\n" - " Outbound time (in us, incl QDIO) : %i\n" - " Outbound count : %i\n" - " Outbound do_QDIO time (in us) : %i\n" - " Outbound do_QDIO count : %i\n\n", + seq_printf(s, " Inbound handler time (in us) : %u\n" + " Inbound handler count : %u\n" + " Inbound do_QDIO time (in us) : %u\n" + " Inbound do_QDIO count : %u\n\n" + " Outbound handler time (in us) : %u\n" + " Outbound handler count : %u\n\n" + " Outbound time (in us, incl QDIO) : %u\n" + " Outbound count : %u\n" + " Outbound do_QDIO time (in us) : %u\n" + " Outbound do_QDIO count : %u\n\n", card->perf_stats.inbound_time, card->perf_stats.inbound_cnt, card->perf_stats.inbound_do_qdio_time, diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c index c1831f5..f2a076a 100644 --- a/drivers/s390/net/qeth_sys.c +++ b/drivers/s390/net/qeth_sys.c @@ -115,7 +115,7 @@ qeth_dev_portno_store(struct device *dev, struct device_attribute *attr, const c return -EPERM; portno = simple_strtoul(buf, &tmp, 16); - if ((portno < 0) || (portno > MAX_PORTNO)){ + if (portno > MAX_PORTNO){ PRINT_WARN("portno 0x%X is out of range\n", portno); return -EINVAL; } diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 5c94a5d..4035920 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -595,10 +595,10 @@ config SCSI_SATA_VIA If unsure, say N. config SCSI_SATA_VITESSE - tristate "VITESSE VSC-7174 SATA support" + tristate "VITESSE VSC-7174 / INTEL 31244 SATA support" depends on SCSI_SATA && PCI help - This option enables support for Vitesse VSC7174 Serial ATA. + This option enables support for Vitesse VSC7174 and Intel 31244 Serial ATA. If unsure, say N. diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 15dc2e0..e513c31 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -117,7 +117,6 @@ obj-$(CONFIG_SCSI_PPA) += ppa.o obj-$(CONFIG_SCSI_IMM) += imm.o obj-$(CONFIG_JAZZ_ESP) += NCR53C9x.o jazz_esp.o obj-$(CONFIG_SUN3X_ESP) += NCR53C9x.o sun3x_esp.o -obj-$(CONFIG_SCSI_DEBUG) += scsi_debug.o obj-$(CONFIG_SCSI_FCAL) += fcal.o obj-$(CONFIG_SCSI_LASI700) += 53c700.o lasi700.o obj-$(CONFIG_SCSI_NSP32) += nsp32.o @@ -148,6 +147,9 @@ obj-$(CONFIG_BLK_DEV_SR) += sr_mod.o obj-$(CONFIG_CHR_DEV_SG) += sg.o obj-$(CONFIG_CHR_DEV_SCH) += ch.o +# This goes last, so that "real" scsi devices probe earlier +obj-$(CONFIG_SCSI_DEBUG) += scsi_debug.o + scsi_mod-y += scsi.o hosts.o scsi_ioctl.o constants.o \ scsicam.o scsi_error.o scsi_lib.o \ scsi_scan.o scsi_sysfs.o \ diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index a1ddbba..ffba656 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -513,6 +513,138 @@ static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, u32 opts) pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16); } +static int ahci_poll_register(void __iomem *reg, u32 mask, u32 val, + unsigned long interval_msec, + unsigned long timeout_msec) +{ + unsigned long timeout; + u32 tmp; + + timeout = jiffies + (timeout_msec * HZ) / 1000; + do { + tmp = readl(reg); + if ((tmp & mask) == val) + return 0; + msleep(interval_msec); + } while (time_before(jiffies, timeout)); + + return -1; +} + +static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) +{ + struct ahci_host_priv *hpriv = ap->host_set->private_data; + struct ahci_port_priv *pp = ap->private_data; + void __iomem *mmio = ap->host_set->mmio_base; + void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); + const u32 cmd_fis_len = 5; /* five dwords */ + const char *reason = NULL; + struct ata_taskfile tf; + u8 *fis; + int rc; + + DPRINTK("ENTER\n"); + + /* prepare for SRST (AHCI-1.1 10.4.1) */ + rc = ahci_stop_engine(ap); + if (rc) { + reason = "failed to stop engine"; + goto fail_restart; + } + + /* check BUSY/DRQ, perform Command List Override if necessary */ + ahci_tf_read(ap, &tf); + if (tf.command & (ATA_BUSY | ATA_DRQ)) { + u32 tmp; + + if (!(hpriv->cap & HOST_CAP_CLO)) { + rc = -EIO; + reason = "port busy but no CLO"; + goto fail_restart; + } + + tmp = readl(port_mmio + PORT_CMD); + tmp |= PORT_CMD_CLO; + writel(tmp, port_mmio + PORT_CMD); + readl(port_mmio + PORT_CMD); /* flush */ + + if (ahci_poll_register(port_mmio + PORT_CMD, PORT_CMD_CLO, 0x0, + 1, 500)) { + rc = -EIO; + reason = "CLO failed"; + goto fail_restart; + } + } + + /* restart engine */ + ahci_start_engine(ap); + + ata_tf_init(ap, &tf, 0); + fis = pp->cmd_tbl; + + /* issue the first D2H Register FIS */ + ahci_fill_cmd_slot(pp, cmd_fis_len | AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY); + + tf.ctl |= ATA_SRST; + ata_tf_to_fis(&tf, fis, 0); + fis[1] &= ~(1 << 7); /* turn off Command FIS bit */ + + writel(1, port_mmio + PORT_CMD_ISSUE); + readl(port_mmio + PORT_CMD_ISSUE); /* flush */ + + if (ahci_poll_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x0, 1, 500)) { + rc = -EIO; + reason = "1st FIS failed"; + goto fail; + } + + /* spec says at least 5us, but be generous and sleep for 1ms */ + msleep(1); + + /* issue the second D2H Register FIS */ + ahci_fill_cmd_slot(pp, cmd_fis_len); + + tf.ctl &= ~ATA_SRST; + ata_tf_to_fis(&tf, fis, 0); + fis[1] &= ~(1 << 7); /* turn off Command FIS bit */ + + writel(1, port_mmio + PORT_CMD_ISSUE); + readl(port_mmio + PORT_CMD_ISSUE); /* flush */ + + /* spec mandates ">= 2ms" before checking status. + * We wait 150ms, because that was the magic delay used for + * ATAPI devices in Hale Landis's ATADRVR, for the period of time + * between when the ATA command register is written, and then + * status is checked. Because waiting for "a while" before + * checking status is fine, post SRST, we perform this magic + * delay here as well. + */ + msleep(150); + + *class = ATA_DEV_NONE; + if (sata_dev_present(ap)) { + if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { + rc = -EIO; + reason = "device not ready"; + goto fail; + } + *class = ahci_dev_classify(ap); + } + + DPRINTK("EXIT, class=%u\n", *class); + return 0; + + fail_restart: + ahci_start_engine(ap); + fail: + if (verbose) + printk(KERN_ERR "ata%u: softreset failed (%s)\n", + ap->id, reason); + else + DPRINTK("EXIT, rc=%d reason=\"%s\"\n", rc, reason); + return rc; +} + static int ahci_hardreset(struct ata_port *ap, int verbose, unsigned int *class) { int rc; @@ -553,7 +685,8 @@ static void ahci_postreset(struct ata_port *ap, unsigned int *class) static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes) { - return ata_drive_probe_reset(ap, NULL, NULL, ahci_hardreset, + return ata_drive_probe_reset(ap, ata_std_probeinit, + ahci_softreset, ahci_hardreset, ahci_postreset, classes); } diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c index a93336a..96b4d21 100644 --- a/drivers/scsi/libata-bmdma.c +++ b/drivers/scsi/libata-bmdma.c @@ -214,6 +214,8 @@ static void ata_exec_command_pio(struct ata_port *ap, const struct ata_taskfile * Issues MMIO write to ATA command register, with proper * synchronization with interrupt handler / other threads. * + * FIXME: missing write posting for 400nS delay enforcement + * * LOCKING: * spin_lock_irqsave(host_set lock) */ @@ -648,6 +650,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, goto err_out_regions; } + /* FIXME: If we get no DMA mask we should fall back to PIO */ rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); if (rc) goto err_out_regions; @@ -699,5 +702,41 @@ err_out: return rc; } +/** + * ata_pci_clear_simplex - attempt to kick device out of simplex + * @pdev: PCI device + * + * Some PCI ATA devices report simplex mode but in fact can be told to + * enter non simplex mode. This implements the neccessary logic to + * perform the task on such devices. Calling it on other devices will + * have -undefined- behaviour. + */ + +int ata_pci_clear_simplex(struct pci_dev *pdev) +{ + unsigned long bmdma = pci_resource_start(pdev, 4); + u8 simplex; + + if (bmdma == 0) + return -ENOENT; + + simplex = inb(bmdma + 0x02); + outb(simplex & 0x60, bmdma + 0x02); + simplex = inb(bmdma + 0x02); + if (simplex & 0x80) + return -EOPNOTSUPP; + return 0; +} + +unsigned long ata_pci_default_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long xfer_mask) +{ + /* Filter out DMA modes if the device has been configured by + the BIOS as PIO only */ + + if (ap->ioaddr.bmdma_addr == 0) + xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); + return xfer_mask; +} + #endif /* CONFIG_PCI */ diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 64dce00..0314abd 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -962,6 +962,8 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev, spin_unlock_irqrestore(&ap->host_set->lock, flags); if (!wait_for_completion_timeout(&wait, ATA_TMOUT_INTERNAL)) { + ata_port_flush_task(ap); + spin_lock_irqsave(&ap->host_set->lock, flags); /* We're racing with irq here. If we lose, the @@ -1219,13 +1221,6 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, * common ATA, ATAPI feature tests */ - /* we require DMA support (bits 8 of word 49) */ - if (!ata_id_has_dma(id)) { - printk(KERN_DEBUG "ata%u: no dma\n", ap->id); - rc = -EINVAL; - goto err_out_nosup; - } - /* find max transfer mode; for printk only */ xfer_mask = ata_id_xfermask(id); @@ -1737,7 +1732,7 @@ static int ata_host_set_pio(struct ata_port *ap) continue; if (!dev->pio_mode) { - printk(KERN_WARNING "ata%u: no PIO support\n", ap->id); + printk(KERN_WARNING "ata%u: no PIO support for device %d.\n", ap->id, i); return -1; } @@ -1999,9 +1994,19 @@ static unsigned int ata_bus_softreset(struct ata_port *ap, * status is checked. Because waiting for "a while" before * checking status is fine, post SRST, we perform this magic * delay here as well. + * + * Old drivers/ide uses the 2mS rule and then waits for ready */ msleep(150); + + /* Before we perform post reset processing we want to see if + the bus shows 0xFF because the odd clown forgets the D7 pulldown + resistor */ + + if (ata_check_status(ap) == 0xFF) + return 1; /* Positive is failure for some reason */ + ata_bus_post_reset(ap, devmask); return 0; @@ -2551,48 +2556,72 @@ int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, } static const char * const ata_dma_blacklist [] = { - "WDC AC11000H", - "WDC AC22100H", - "WDC AC32500H", - "WDC AC33100H", - "WDC AC31600H", - "WDC AC32100H", - "WDC AC23200L", - "Compaq CRD-8241B", - "CRD-8400B", - "CRD-8480B", - "CRD-8482B", - "CRD-84", - "SanDisk SDP3B", - "SanDisk SDP3B-64", - "SANYO CD-ROM CRD", - "HITACHI CDR-8", - "HITACHI CDR-8335", - "HITACHI CDR-8435", - "Toshiba CD-ROM XM-6202B", - "TOSHIBA CD-ROM XM-1702BC", - "CD-532E-A", - "E-IDE CD-ROM CR-840", - "CD-ROM Drive/F5A", - "WPI CDD-820", - "SAMSUNG CD-ROM SC-148C", - "SAMSUNG CD-ROM SC", - "SanDisk SDP3B-64", - "ATAPI CD-ROM DRIVE 40X MAXIMUM", - "_NEC DV5800A", + "WDC AC11000H", NULL, + "WDC AC22100H", NULL, + "WDC AC32500H", NULL, + "WDC AC33100H", NULL, + "WDC AC31600H", NULL, + "WDC AC32100H", "24.09P07", + "WDC AC23200L", "21.10N21", + "Compaq CRD-8241B", NULL, + "CRD-8400B", NULL, + "CRD-8480B", NULL, + "CRD-8482B", NULL, + "CRD-84", NULL, + "SanDisk SDP3B", NULL, + "SanDisk SDP3B-64", NULL, + "SANYO CD-ROM CRD", NULL, + "HITACHI CDR-8", NULL, + "HITACHI CDR-8335", NULL, + "HITACHI CDR-8435", NULL, + "Toshiba CD-ROM XM-6202B", NULL, + "TOSHIBA CD-ROM XM-1702BC", NULL, + "CD-532E-A", NULL, + "E-IDE CD-ROM CR-840", NULL, + "CD-ROM Drive/F5A", NULL, + "WPI CDD-820", NULL, + "SAMSUNG CD-ROM SC-148C", NULL, + "SAMSUNG CD-ROM SC", NULL, + "SanDisk SDP3B-64", NULL, + "ATAPI CD-ROM DRIVE 40X MAXIMUM",NULL, + "_NEC DV5800A", NULL, + "SAMSUNG CD-ROM SN-124", "N001" }; + +static int ata_strim(char *s, size_t len) +{ + len = strnlen(s, len); + + /* ATAPI specifies that empty space is blank-filled; remove blanks */ + while ((len > 0) && (s[len - 1] == ' ')) { + len--; + s[len] = 0; + } + return len; +} static int ata_dma_blacklisted(const struct ata_device *dev) { - unsigned char model_num[41]; + unsigned char model_num[40]; + unsigned char model_rev[16]; + unsigned int nlen, rlen; int i; - ata_id_c_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num)); - - for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i++) - if (!strcmp(ata_dma_blacklist[i], model_num)) - return 1; + ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS, + sizeof(model_num)); + ata_id_string(dev->id, model_rev, ATA_ID_FW_REV_OFS, + sizeof(model_rev)); + nlen = ata_strim(model_num, sizeof(model_num)); + rlen = ata_strim(model_rev, sizeof(model_rev)); + for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i += 2) { + if (!strncmp(ata_dma_blacklist[i], model_num, nlen)) { + if (ata_dma_blacklist[i+1] == NULL) + return 1; + if (!strncmp(ata_dma_blacklist[i], model_rev, rlen)) + return 1; + } + } return 0; } @@ -2863,6 +2892,8 @@ void ata_qc_prep(struct ata_queued_cmd *qc) ata_fill_sg(qc); } +void ata_noop_qc_prep(struct ata_queued_cmd *qc) { } + /** * ata_sg_init_one - Associate command with memory buffer * @qc: Command to be associated @@ -3907,7 +3938,6 @@ static inline int ata_should_dma_map(struct ata_queued_cmd *qc) case ATA_PROT_ATAPI: case ATA_PROT_PIO: - case ATA_PROT_PIO_MULT: if (ap->flags & ATA_FLAG_PIO_DMA) return 1; @@ -4199,14 +4229,17 @@ void ata_bmdma_setup(struct ata_queued_cmd *qc) void ata_bmdma_irq_clear(struct ata_port *ap) { - if (ap->flags & ATA_FLAG_MMIO) { - void __iomem *mmio = ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS; - writeb(readb(mmio), mmio); - } else { - unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS; - outb(inb(addr), addr); - } + if (!ap->ioaddr.bmdma_addr) + return; + if (ap->flags & ATA_FLAG_MMIO) { + void __iomem *mmio = + ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS; + writeb(readb(mmio), mmio); + } else { + unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS; + outb(inb(addr), addr); + } } @@ -4337,9 +4370,9 @@ idle_irq: #ifdef ATA_IRQ_TRAP if ((ap->stats.idle_irq % 1000) == 0) { - handled = 1; ata_irq_ack(ap, 0); /* debug trap */ printk(KERN_WARNING "ata%d: irq trap\n", ap->id); + return 1; } #endif return 0; /* irq not handled */ @@ -5064,6 +5097,7 @@ EXPORT_SYMBOL_GPL(ata_port_stop); EXPORT_SYMBOL_GPL(ata_host_stop); EXPORT_SYMBOL_GPL(ata_interrupt); EXPORT_SYMBOL_GPL(ata_qc_prep); +EXPORT_SYMBOL_GPL(ata_noop_qc_prep); EXPORT_SYMBOL_GPL(ata_bmdma_setup); EXPORT_SYMBOL_GPL(ata_bmdma_start); EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear); @@ -5109,6 +5143,8 @@ EXPORT_SYMBOL_GPL(ata_pci_init_one); EXPORT_SYMBOL_GPL(ata_pci_remove_one); EXPORT_SYMBOL_GPL(ata_pci_device_suspend); EXPORT_SYMBOL_GPL(ata_pci_device_resume); +EXPORT_SYMBOL_GPL(ata_pci_default_filter); +EXPORT_SYMBOL_GPL(ata_pci_clear_simplex); #endif /* CONFIG_PCI */ EXPORT_SYMBOL_GPL(ata_device_suspend); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index bd9f217..a1259b2 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -521,13 +521,11 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, printk(KERN_WARNING "ata%u: no sense translation for status: 0x%02x\n", id, drv_stat); - /* For our last chance pick, use medium read error because - * it's much more common than an ATA drive telling you a write - * has failed. - */ - *sk = MEDIUM_ERROR; - *asc = 0x11; /* "unrecovered read error" */ - *ascq = 0x04; /* "auto-reallocation failed" */ + /* We need a sensible error return here, which is tricky, and one + that won't cause people to do things like return a disk wrongly */ + *sk = ABORTED_COMMAND; + *asc = 0x00; + *ascq = 0x00; translate_done: printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x to " @@ -672,6 +670,41 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc) } } +static void ata_scsi_sdev_config(struct scsi_device *sdev) +{ + sdev->use_10_for_rw = 1; + sdev->use_10_for_ms = 1; +} + +static void ata_scsi_dev_config(struct scsi_device *sdev, + struct ata_device *dev) +{ + unsigned int max_sectors; + + /* TODO: 2048 is an arbitrary number, not the + * hardware maximum. This should be increased to + * 65534 when Jens Axboe's patch for dynamically + * determining max_sectors is merged. + */ + max_sectors = ATA_MAX_SECTORS; + if (dev->flags & ATA_DFLAG_LBA48) + max_sectors = 2048; + if (dev->max_sectors) + max_sectors = dev->max_sectors; + + blk_queue_max_sectors(sdev->request_queue, max_sectors); + + /* + * SATA DMA transfers must be multiples of 4 byte, so + * we need to pad ATAPI transfers using an extra sg. + * Decrement max hw segments accordingly. + */ + if (dev->class == ATA_DEV_ATAPI) { + request_queue_t *q = sdev->request_queue; + blk_queue_max_hw_segments(q, q->max_hw_segments - 1); + } +} + /** * ata_scsi_slave_config - Set SCSI device attributes * @sdev: SCSI device to examine @@ -686,41 +719,18 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc) int ata_scsi_slave_config(struct scsi_device *sdev) { - sdev->use_10_for_rw = 1; - sdev->use_10_for_ms = 1; + ata_scsi_sdev_config(sdev); blk_queue_max_phys_segments(sdev->request_queue, LIBATA_MAX_PRD); if (sdev->id < ATA_MAX_DEVICES) { struct ata_port *ap; struct ata_device *dev; - unsigned int max_sectors; ap = (struct ata_port *) &sdev->host->hostdata[0]; dev = &ap->device[sdev->id]; - /* TODO: 2048 is an arbitrary number, not the - * hardware maximum. This should be increased to - * 65534 when Jens Axboe's patch for dynamically - * determining max_sectors is merged. - */ - max_sectors = ATA_MAX_SECTORS; - if (dev->flags & ATA_DFLAG_LBA48) - max_sectors = 2048; - if (dev->max_sectors) - max_sectors = dev->max_sectors; - - blk_queue_max_sectors(sdev->request_queue, max_sectors); - - /* - * SATA DMA transfers must be multiples of 4 byte, so - * we need to pad ATAPI transfers using an extra sg. - * Decrement max hw segments accordingly. - */ - if (dev->class == ATA_DEV_ATAPI) { - request_queue_t *q = sdev->request_queue; - blk_queue_max_hw_segments(q, q->max_hw_segments - 1); - } + ata_scsi_dev_config(sdev, dev); } return 0; /* scsi layer doesn't check return value, sigh */ @@ -1552,7 +1562,7 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args, * @buflen: Response buffer length. * * Returns standard device identification data associated - * with non-EVPD INQUIRY command output. + * with non-VPD INQUIRY command output. * * LOCKING: * spin_lock_irqsave(host_set lock) @@ -1603,12 +1613,12 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, } /** - * ata_scsiop_inq_00 - Simulate INQUIRY EVPD page 0, list of pages + * ata_scsiop_inq_00 - Simulate INQUIRY VPD page 0, list of pages * @args: device IDENTIFY data / SCSI command of interest. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @buflen: Response buffer length. * - * Returns list of inquiry EVPD pages available. + * Returns list of inquiry VPD pages available. * * LOCKING: * spin_lock_irqsave(host_set lock) @@ -1622,7 +1632,7 @@ unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf, 0x80, /* page 0x80, unit serial no page */ 0x83 /* page 0x83, device ident page */ }; - rbuf[3] = sizeof(pages); /* number of supported EVPD pages */ + rbuf[3] = sizeof(pages); /* number of supported VPD pages */ if (buflen > 6) memcpy(rbuf + 4, pages, sizeof(pages)); @@ -1631,7 +1641,7 @@ unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf, } /** - * ata_scsiop_inq_80 - Simulate INQUIRY EVPD page 80, device serial number + * ata_scsiop_inq_80 - Simulate INQUIRY VPD page 80, device serial number * @args: device IDENTIFY data / SCSI command of interest. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @buflen: Response buffer length. @@ -1660,16 +1670,16 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf, return 0; } -static const char * const inq_83_str = "Linux ATA-SCSI simulator"; - /** - * ata_scsiop_inq_83 - Simulate INQUIRY EVPD page 83, device identity + * ata_scsiop_inq_83 - Simulate INQUIRY VPD page 83, device identity * @args: device IDENTIFY data / SCSI command of interest. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @buflen: Response buffer length. * - * Returns device identification. Currently hardcoded to - * return "Linux ATA-SCSI simulator". + * Yields two logical unit device identification designators: + * - vendor specific ASCII containing the ATA serial number + * - SAT defined "t10 vendor id based" containing ASCII vendor + * name ("ATA "), model and serial numbers. * * LOCKING: * spin_lock_irqsave(host_set lock) @@ -1678,16 +1688,39 @@ static const char * const inq_83_str = "Linux ATA-SCSI simulator"; unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen) { - rbuf[1] = 0x83; /* this page code */ - rbuf[3] = 4 + strlen(inq_83_str); /* page len */ + int num; + const int sat_model_serial_desc_len = 68; + const int ata_model_byte_len = 40; - /* our one and only identification descriptor (vendor-specific) */ - if (buflen > (strlen(inq_83_str) + 4 + 4 - 1)) { - rbuf[4 + 0] = 2; /* code set: ASCII */ - rbuf[4 + 3] = strlen(inq_83_str); - memcpy(rbuf + 4 + 4, inq_83_str, strlen(inq_83_str)); + rbuf[1] = 0x83; /* this page code */ + num = 4; + + if (buflen > (ATA_SERNO_LEN + num + 3)) { + /* piv=0, assoc=lu, code_set=ACSII, designator=vendor */ + rbuf[num + 0] = 2; + rbuf[num + 3] = ATA_SERNO_LEN; + num += 4; + ata_id_string(args->id, (unsigned char *) rbuf + num, + ATA_ID_SERNO_OFS, ATA_SERNO_LEN); + num += ATA_SERNO_LEN; } - + if (buflen > (sat_model_serial_desc_len + num + 3)) { + /* SAT defined lu model and serial numbers descriptor */ + /* piv=0, assoc=lu, code_set=ACSII, designator=t10 vendor id */ + rbuf[num + 0] = 2; + rbuf[num + 1] = 1; + rbuf[num + 3] = sat_model_serial_desc_len; + num += 4; + memcpy(rbuf + num, "ATA ", 8); + num += 8; + ata_id_string(args->id, (unsigned char *) rbuf + num, + ATA_ID_PROD_OFS, ata_model_byte_len); + num += ata_model_byte_len; + ata_id_string(args->id, (unsigned char *) rbuf + num, + ATA_ID_SERNO_OFS, ATA_SERNO_LEN); + num += ATA_SERNO_LEN; + } + rbuf[3] = num - 4; /* page len (assume less than 256 bytes) */ return 0; } @@ -2366,9 +2399,6 @@ ata_scsi_map_proto(u8 byte1) case 4: /* PIO Data-in */ case 5: /* PIO Data-out */ - if (byte1 & 0xe0) { - return ATA_PROT_PIO_MULT; - } return ATA_PROT_PIO; case 10: /* Device Reset */ @@ -2407,6 +2437,10 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd) if ((tf->protocol = ata_scsi_map_proto(scsicmd[1])) == ATA_PROT_UNKNOWN) goto invalid_fld; + if (scsicmd[1] & 0xe0) + /* PIO multi not supported yet */ + goto invalid_fld; + /* * 12 and 16 byte CDBs use different offsets to * provide the various register values. diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index b3dc5f8..3c85c4b 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -321,7 +321,7 @@ static int adma_fill_sg(struct ata_queued_cmd *qc) = (pFLAGS & pEND) ? 0 : cpu_to_le32(pp->pkt_dma + i + 4); i += 4; - VPRINTK("PRD[%u] = (0x%lX, 0x%X)\n", nelem, + VPRINTK("PRD[%u] = (0x%lX, 0x%X)\n", i/4, (unsigned long)addr, len); } return i; diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 874c5be..275ed9b 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -1262,6 +1262,7 @@ static u8 mv_get_crpb_status(struct ata_port *ap) void __iomem *port_mmio = mv_ap_base(ap); struct mv_port_priv *pp = ap->private_data; u32 out_ptr; + u8 ata_status; out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); @@ -1269,6 +1270,8 @@ static u8 mv_get_crpb_status(struct ata_port *ap) WARN_ON(((out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) != pp->rsp_consumer); + ata_status = pp->crpb[pp->rsp_consumer].flags >> CRPB_FLAG_STATUS_SHIFT; + /* increment our consumer index... */ pp->rsp_consumer = mv_inc_q_index(&pp->rsp_consumer); @@ -1283,7 +1286,7 @@ static u8 mv_get_crpb_status(struct ata_port *ap) writelfl(out_ptr, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); /* Return ATA status register for completed CRPB */ - return (pp->crpb[pp->rsp_consumer].flags >> CRPB_FLAG_STATUS_SHIFT); + return ata_status; } /** diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index 051e47d..724f0ed 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -56,33 +56,35 @@ #define DRV_NAME "sata_svw" #define DRV_VERSION "1.07" -/* Taskfile registers offsets */ -#define K2_SATA_TF_CMD_OFFSET 0x00 -#define K2_SATA_TF_DATA_OFFSET 0x00 -#define K2_SATA_TF_ERROR_OFFSET 0x04 -#define K2_SATA_TF_NSECT_OFFSET 0x08 -#define K2_SATA_TF_LBAL_OFFSET 0x0c -#define K2_SATA_TF_LBAM_OFFSET 0x10 -#define K2_SATA_TF_LBAH_OFFSET 0x14 -#define K2_SATA_TF_DEVICE_OFFSET 0x18 -#define K2_SATA_TF_CMDSTAT_OFFSET 0x1c -#define K2_SATA_TF_CTL_OFFSET 0x20 - -/* DMA base */ -#define K2_SATA_DMA_CMD_OFFSET 0x30 - -/* SCRs base */ -#define K2_SATA_SCR_STATUS_OFFSET 0x40 -#define K2_SATA_SCR_ERROR_OFFSET 0x44 -#define K2_SATA_SCR_CONTROL_OFFSET 0x48 - -/* Others */ -#define K2_SATA_SICR1_OFFSET 0x80 -#define K2_SATA_SICR2_OFFSET 0x84 -#define K2_SATA_SIM_OFFSET 0x88 - -/* Port stride */ -#define K2_SATA_PORT_OFFSET 0x100 +enum { + /* Taskfile registers offsets */ + K2_SATA_TF_CMD_OFFSET = 0x00, + K2_SATA_TF_DATA_OFFSET = 0x00, + K2_SATA_TF_ERROR_OFFSET = 0x04, + K2_SATA_TF_NSECT_OFFSET = 0x08, + K2_SATA_TF_LBAL_OFFSET = 0x0c, + K2_SATA_TF_LBAM_OFFSET = 0x10, + K2_SATA_TF_LBAH_OFFSET = 0x14, + K2_SATA_TF_DEVICE_OFFSET = 0x18, + K2_SATA_TF_CMDSTAT_OFFSET = 0x1c, + K2_SATA_TF_CTL_OFFSET = 0x20, + + /* DMA base */ + K2_SATA_DMA_CMD_OFFSET = 0x30, + + /* SCRs base */ + K2_SATA_SCR_STATUS_OFFSET = 0x40, + K2_SATA_SCR_ERROR_OFFSET = 0x44, + K2_SATA_SCR_CONTROL_OFFSET = 0x48, + + /* Others */ + K2_SATA_SICR1_OFFSET = 0x80, + K2_SATA_SICR2_OFFSET = 0x84, + K2_SATA_SIM_OFFSET = 0x88, + + /* Port stride */ + K2_SATA_PORT_OFFSET = 0x100, +}; static u8 k2_stat_check_status(struct ata_port *ap); diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index ee75b9b..9701a80 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -47,52 +47,58 @@ #include <linux/libata.h> #define DRV_NAME "sata_vsc" -#define DRV_VERSION "1.1" - -/* Interrupt register offsets (from chip base address) */ -#define VSC_SATA_INT_STAT_OFFSET 0x00 -#define VSC_SATA_INT_MASK_OFFSET 0x04 - -/* Taskfile registers offsets */ -#define VSC_SATA_TF_CMD_OFFSET 0x00 -#define VSC_SATA_TF_DATA_OFFSET 0x00 -#define VSC_SATA_TF_ERROR_OFFSET 0x04 -#define VSC_SATA_TF_FEATURE_OFFSET 0x06 -#define VSC_SATA_TF_NSECT_OFFSET 0x08 -#define VSC_SATA_TF_LBAL_OFFSET 0x0c -#define VSC_SATA_TF_LBAM_OFFSET 0x10 -#define VSC_SATA_TF_LBAH_OFFSET 0x14 -#define VSC_SATA_TF_DEVICE_OFFSET 0x18 -#define VSC_SATA_TF_STATUS_OFFSET 0x1c -#define VSC_SATA_TF_COMMAND_OFFSET 0x1d -#define VSC_SATA_TF_ALTSTATUS_OFFSET 0x28 -#define VSC_SATA_TF_CTL_OFFSET 0x29 - -/* DMA base */ -#define VSC_SATA_UP_DESCRIPTOR_OFFSET 0x64 -#define VSC_SATA_UP_DATA_BUFFER_OFFSET 0x6C -#define VSC_SATA_DMA_CMD_OFFSET 0x70 - -/* SCRs base */ -#define VSC_SATA_SCR_STATUS_OFFSET 0x100 -#define VSC_SATA_SCR_ERROR_OFFSET 0x104 -#define VSC_SATA_SCR_CONTROL_OFFSET 0x108 - -/* Port stride */ -#define VSC_SATA_PORT_OFFSET 0x200 - -/* Error interrupt status bit offsets */ -#define VSC_SATA_INT_ERROR_E_OFFSET 2 -#define VSC_SATA_INT_ERROR_P_OFFSET 4 -#define VSC_SATA_INT_ERROR_T_OFFSET 5 -#define VSC_SATA_INT_ERROR_M_OFFSET 1 +#define DRV_VERSION "1.2" + +enum { + /* Interrupt register offsets (from chip base address) */ + VSC_SATA_INT_STAT_OFFSET = 0x00, + VSC_SATA_INT_MASK_OFFSET = 0x04, + + /* Taskfile registers offsets */ + VSC_SATA_TF_CMD_OFFSET = 0x00, + VSC_SATA_TF_DATA_OFFSET = 0x00, + VSC_SATA_TF_ERROR_OFFSET = 0x04, + VSC_SATA_TF_FEATURE_OFFSET = 0x06, + VSC_SATA_TF_NSECT_OFFSET = 0x08, + VSC_SATA_TF_LBAL_OFFSET = 0x0c, + VSC_SATA_TF_LBAM_OFFSET = 0x10, + VSC_SATA_TF_LBAH_OFFSET = 0x14, + VSC_SATA_TF_DEVICE_OFFSET = 0x18, + VSC_SATA_TF_STATUS_OFFSET = 0x1c, + VSC_SATA_TF_COMMAND_OFFSET = 0x1d, + VSC_SATA_TF_ALTSTATUS_OFFSET = 0x28, + VSC_SATA_TF_CTL_OFFSET = 0x29, + + /* DMA base */ + VSC_SATA_UP_DESCRIPTOR_OFFSET = 0x64, + VSC_SATA_UP_DATA_BUFFER_OFFSET = 0x6C, + VSC_SATA_DMA_CMD_OFFSET = 0x70, + + /* SCRs base */ + VSC_SATA_SCR_STATUS_OFFSET = 0x100, + VSC_SATA_SCR_ERROR_OFFSET = 0x104, + VSC_SATA_SCR_CONTROL_OFFSET = 0x108, + + /* Port stride */ + VSC_SATA_PORT_OFFSET = 0x200, + + /* Error interrupt status bit offsets */ + VSC_SATA_INT_ERROR_CRC = 0x40, + VSC_SATA_INT_ERROR_T = 0x20, + VSC_SATA_INT_ERROR_P = 0x10, + VSC_SATA_INT_ERROR_R = 0x8, + VSC_SATA_INT_ERROR_E = 0x4, + VSC_SATA_INT_ERROR_M = 0x2, + VSC_SATA_INT_PHY_CHANGE = 0x1, + VSC_SATA_INT_ERROR = (VSC_SATA_INT_ERROR_CRC | VSC_SATA_INT_ERROR_T | \ + VSC_SATA_INT_ERROR_P | VSC_SATA_INT_ERROR_R | \ + VSC_SATA_INT_ERROR_E | VSC_SATA_INT_ERROR_M | \ + VSC_SATA_INT_PHY_CHANGE), +}; + + #define is_vsc_sata_int_err(port_idx, int_status) \ - (int_status & ((1 << (VSC_SATA_INT_ERROR_E_OFFSET + (8 * port_idx))) | \ - (1 << (VSC_SATA_INT_ERROR_P_OFFSET + (8 * port_idx))) | \ - (1 << (VSC_SATA_INT_ERROR_T_OFFSET + (8 * port_idx))) | \ - (1 << (VSC_SATA_INT_ERROR_M_OFFSET + (8 * port_idx))) \ - )\ - ) + (int_status & (VSC_SATA_INT_ERROR << (8 * port_idx))) static u32 vsc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg) @@ -215,14 +221,6 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, ap = host_set->ports[i]; - if (is_vsc_sata_int_err(i, int_status)) { - u32 err_status; - printk(KERN_DEBUG "%s: ignoring interrupt(s)\n", __FUNCTION__); - err_status = ap ? vsc_sata_scr_read(ap, SCR_ERROR) : 0; - vsc_sata_scr_write(ap, SCR_ERROR, err_status); - handled++; - } - if (ap && !(ap->flags & (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) { struct ata_queued_cmd *qc; @@ -230,12 +228,26 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, qc = ata_qc_from_tag(ap, ap->active_tag); if (qc && (!(qc->tf.ctl & ATA_NIEN))) { handled += ata_host_intr(ap, qc); - } else { - printk(KERN_DEBUG "%s: ignoring interrupt(s)\n", __FUNCTION__); + } else if (is_vsc_sata_int_err(i, int_status)) { + /* + * On some chips (i.e. Intel 31244), an error + * interrupt will sneak in at initialization + * time (phy state changes). Clearing the SCR + * error register is not required, but it prevents + * the phy state change interrupts from recurring + * later. + */ + u32 err_status; + err_status = vsc_sata_scr_read(ap, SCR_ERROR); + printk(KERN_DEBUG "%s: clearing interrupt, " + "status %x; sata err status %x\n", + __FUNCTION__, + int_status, err_status); + vsc_sata_scr_write(ap, SCR_ERROR, err_status); + /* Clear interrupt status */ ata_chk_status(ap); handled++; } - } } } diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index 8c5c276..7572665 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c @@ -375,23 +375,18 @@ static void serial21285_setup_ports(void) } #ifdef CONFIG_SERIAL_21285_CONSOLE +static void serial21285_console_putchar(struct uart_port *port, int ch) +{ + while (*CSR_UARTFLG & 0x20) + barrier(); + *CSR_UARTDR = ch; +} static void serial21285_console_write(struct console *co, const char *s, unsigned int count) { - int i; - - for (i = 0; i < count; i++) { - while (*CSR_UARTFLG & 0x20) - barrier(); - *CSR_UARTDR = s[i]; - if (s[i] == '\n') { - while (*CSR_UARTFLG & 0x20) - barrier(); - *CSR_UARTDR = '\r'; - } - } + uart_console_write(&serial21285_port, s, count, serial21285_console_putchar); } static void __init diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 7aca22c..5996d3c 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -2182,6 +2182,14 @@ static inline void wait_for_xmitr(struct uart_8250_port *up, int bits) } } +static void serial8250_console_putchar(struct uart_port *port, int ch) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + + wait_for_xmitr(up, UART_LSR_THRE); + serial_out(up, UART_TX, ch); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -2193,7 +2201,6 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) { struct uart_8250_port *up = &serial8250_ports[co->index]; unsigned int ier; - int i; touch_nmi_watchdog(); @@ -2207,22 +2214,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) else serial_out(up, UART_IER, 0); - /* - * Now, do each character - */ - for (i = 0; i < count; i++, s++) { - wait_for_xmitr(up, UART_LSR_THRE); - - /* - * Send the character out. - * If a LF, also do CR... - */ - serial_out(up, UART_TX, *s); - if (*s == 10) { - wait_for_xmitr(up, UART_LSR_THRE); - serial_out(up, UART_TX, 13); - } - } + uart_console_write(&up->port, s, count, serial8250_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c index 59ba5d9..7e51119 100644 --- a/drivers/serial/8250_early.c +++ b/drivers/serial/8250_early.c @@ -74,7 +74,7 @@ static void __init wait_for_xmitr(struct uart_port *port) } } -static void __init putc(struct uart_port *port, unsigned char c) +static void __init putc(struct uart_port *port, int c) { wait_for_xmitr(port); serial_out(port, UART_TX, c); @@ -89,12 +89,7 @@ static void __init early_uart_write(struct console *console, const char *s, unsi ier = serial_in(port, UART_IER); serial_out(port, UART_IER, 0); - while (*s && count-- > 0) { - putc(port, *s); - if (*s == '\n') - putc(port, '\r'); - s++; - } + uart_console_write(port, s, count, putc); /* Wait for transmitter to become empty and restore the IER */ wait_for_xmitr(port); diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 321a3b3..e04d5e8 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -591,12 +591,18 @@ static struct uart_amba_port amba_ports[UART_NR] = { #ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE +static void pl010_console_putchar(struct uart_port *port, int ch) +{ + while (!UART_TX_READY(UART_GET_FR(port))) + barrier(); + UART_PUT_CHAR(port, ch); +} + static void pl010_console_write(struct console *co, const char *s, unsigned int count) { struct uart_port *port = &amba_ports[co->index].port; unsigned int status, old_cr; - int i; /* * First save the CR then disable the interrupts @@ -604,21 +610,7 @@ pl010_console_write(struct console *co, const char *s, unsigned int count) old_cr = UART_GET_CR(port); UART_PUT_CR(port, UART01x_CR_UARTEN); - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - do { - status = UART_GET_FR(port); - } while (!UART_TX_READY(status)); - UART_PUT_CHAR(port, s[i]); - if (s[i] == '\n') { - do { - status = UART_GET_FR(port); - } while (!UART_TX_READY(status)); - UART_PUT_CHAR(port, '\r'); - } - } + uart_console_write(port, s, count, pl010_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index 034a029..3d966cf 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -587,14 +587,12 @@ static struct uart_amba_port *amba_ports[UART_NR]; #ifdef CONFIG_SERIAL_AMBA_PL011_CONSOLE -static inline void -pl011_console_write_char(struct uart_amba_port *uap, char ch) +static void pl011_console_putchar(struct uart_port *port, int ch) { - unsigned int status; + struct uart_amba_port *uap = (struct uart_amba_port *)port; - do { - status = readw(uap->port.membase + UART01x_FR); - } while (status & UART01x_FR_TXFF); + while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) + barrier(); writew(ch, uap->port.membase + UART01x_DR); } @@ -603,7 +601,6 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) { struct uart_amba_port *uap = amba_ports[co->index]; unsigned int status, old_cr, new_cr; - int i; clk_enable(uap->clk); @@ -615,14 +612,7 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE; writew(new_cr, uap->port.membase + UART011_CR); - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - pl011_console_write_char(uap, s[i]); - if (s[i] == '\n') - pl011_console_write_char(uap, '\r'); - } + uart_console_write(&uap->port, s, count, pl011_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/at91_serial.c b/drivers/serial/at91_serial.c index 2113feb..6547fe0 100644 --- a/drivers/serial/at91_serial.c +++ b/drivers/serial/at91_serial.c @@ -711,6 +711,12 @@ void __init at91_register_uart(int idx, int port) } #ifdef CONFIG_SERIAL_AT91_CONSOLE +static void at91_console_putchar(struct uart_port *port, int ch) +{ + while (!(UART_GET_CSR(port) & AT91_US_TXRDY)) + barrier(); + UART_PUT_CHAR(port, ch); +} /* * Interrupts are disabled on entering @@ -718,7 +724,7 @@ void __init at91_register_uart(int idx, int port) static void at91_console_write(struct console *co, const char *s, u_int count) { struct uart_port *port = at91_ports + co->index; - unsigned int status, i, imr; + unsigned int status, imr; /* * First, save IMR and then disable interrupts @@ -726,21 +732,7 @@ static void at91_console_write(struct console *co, const char *s, u_int count) imr = UART_GET_IMR(port); /* get interrupt mask */ UART_PUT_IDR(port, AT91_US_RXRDY | AT91_US_TXRDY); - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - do { - status = UART_GET_CSR(port); - } while (!(status & AT91_US_TXRDY)); - UART_PUT_CHAR(port, s[i]); - if (s[i] == '\n') { - do { - status = UART_GET_CSR(port); - } while (!(status & AT91_US_TXRDY)); - UART_PUT_CHAR(port, '\r'); - } - } + uart_console_write(port, s, count, at91_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c index 344022f..29f94bb 100644 --- a/drivers/serial/au1x00_uart.c +++ b/drivers/serial/au1x00_uart.c @@ -1121,6 +1121,14 @@ static inline void wait_for_xmitr(struct uart_8250_port *up) } } +static void au1x00_console_putchar(struct uart_port *port, int ch) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + + wait_for_xmitr(up); + serial_out(up, UART_TX, ch); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -1132,7 +1140,6 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) { struct uart_8250_port *up = &serial8250_ports[co->index]; unsigned int ier; - int i; /* * First save the UER then disable the interrupts @@ -1140,22 +1147,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) ier = serial_in(up, UART_IER); serial_out(up, UART_IER, 0); - /* - * Now, do each character - */ - for (i = 0; i < count; i++, s++) { - wait_for_xmitr(up); - - /* - * Send the character out. - * If a LF, also do CR... - */ - serial_out(up, UART_TX, *s); - if (*s == 10) { - wait_for_xmitr(up); - serial_out(up, UART_TX, 13); - } - } + uart_console_write(&up->port, s, count, au1x00_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c index ce7b2e4..2691112 100644 --- a/drivers/serial/clps711x.c +++ b/drivers/serial/clps711x.c @@ -424,6 +424,13 @@ static struct uart_port clps711x_ports[UART_NR] = { }; #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE +static void clps711xuart_console_putchar(struct uart_port *port, int ch) +{ + while (clps_readl(SYSFLG(port)) & SYSFLG_UTXFF) + barrier(); + clps_writel(ch, UARTDR(port)); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -438,7 +445,6 @@ clps711xuart_console_write(struct console *co, const char *s, { struct uart_port *port = clps711x_ports + co->index; unsigned int status, syscon; - int i; /* * Ensure that the port is enabled. @@ -446,21 +452,7 @@ clps711xuart_console_write(struct console *co, const char *s, syscon = clps_readl(SYSCON(port)); clps_writel(syscon | SYSCON_UARTEN, SYSCON(port)); - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - do { - status = clps_readl(SYSFLG(port)); - } while (status & SYSFLG_UTXFF); - clps_writel(s[i], UARTDR(port)); - if (s[i] == '\n') { - do { - status = clps_readl(SYSFLG(port)); - } while (status & SYSFLG_UTXFF); - clps_writel('\r', UARTDR(port)); - } - } + uart_console_write(port, s, count, clps711xuart_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index ba5541d..bf71bad 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c @@ -674,11 +674,12 @@ static void dz_reset(struct dz_port *dport) } #ifdef CONFIG_SERIAL_DZ_CONSOLE -static void dz_console_put_char(struct dz_port *dport, unsigned char ch) +static void dz_console_putchar(struct uart_port *port, int ch) { + struct dz_port *dport = (struct dz_port *)uport; unsigned long flags; int loops = 2500; - unsigned short tmp = ch; + unsigned short tmp = (unsigned char)ch; /* this code sends stuff out to serial device - spinning its wheels and waiting. */ @@ -694,6 +695,7 @@ static void dz_console_put_char(struct dz_port *dport, unsigned char ch) spin_unlock_irqrestore(&dport->port.lock, flags); } + /* * ------------------------------------------------------------------- * dz_console_print () @@ -710,11 +712,7 @@ static void dz_console_print(struct console *cons, #ifdef DEBUG_DZ prom_printf((char *) str); #endif - while (count--) { - if (*str == '\n') - dz_console_put_char(dport, '\r'); - dz_console_put_char(dport, *str++); - } + uart_console_write(&dport->port, str, count, dz_console_putchar); } static int __init dz_console_setup(struct console *co, char *options) diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 4d53fb5..c3b7a66 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -743,6 +743,13 @@ static void __init imx_init_ports(void) } #ifdef CONFIG_SERIAL_IMX_CONSOLE +static void imx_console_putchar(struct uart_port *port, int ch) +{ + struct imx_port *sport = (struct imx_port *)port; + while ((UTS((u32)sport->port.membase) & UTS_TXFULL)) + barrier(); + URTX0((u32)sport->port.membase) = ch; +} /* * Interrupts are disabled on entering @@ -751,7 +758,7 @@ static void imx_console_write(struct console *co, const char *s, unsigned int count) { struct imx_port *sport = &imx_ports[co->index]; - unsigned int old_ucr1, old_ucr2, i; + unsigned int old_ucr1, old_ucr2; /* * First, save UCR1/2 and then disable interrupts @@ -764,22 +771,7 @@ imx_console_write(struct console *co, const char *s, unsigned int count) & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN); UCR2((u32)sport->port.membase) = old_ucr2 | UCR2_TXEN; - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - - while ((UTS((u32)sport->port.membase) & UTS_TXFULL)) - barrier(); - - URTX0((u32)sport->port.membase) = s[i]; - - if (s[i] == '\n') { - while ((UTS((u32)sport->port.membase) & UTS_TXFULL)) - barrier(); - URTX0((u32)sport->port.membase) = '\r'; - } - } + uart_console_write(&sport->port, s, count, imx_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c index 193722d..6517724 100644 --- a/drivers/serial/ip22zilog.c +++ b/drivers/serial/ip22zilog.c @@ -967,8 +967,9 @@ static struct zilog_layout * __init get_zs(int chip) #define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */ #ifdef CONFIG_SERIAL_IP22_ZILOG_CONSOLE -static void ip22zilog_put_char(struct zilog_channel *channel, unsigned char ch) +static void ip22zilog_put_char(struct uart_port *port, int ch) { + struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); int loops = ZS_PUT_CHAR_MAX_DELAY; /* This is a timed polling loop so do not switch the explicit @@ -992,16 +993,10 @@ static void ip22zilog_console_write(struct console *con, const char *s, unsigned int count) { struct uart_ip22zilog_port *up = &ip22zilog_port_table[con->index]; - struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(&up->port); unsigned long flags; - int i; spin_lock_irqsave(&up->port.lock, flags); - for (i = 0; i < count; i++, s++) { - ip22zilog_put_char(channel, *s); - if (*s == 10) - ip22zilog_put_char(channel, 13); - } + uart_console_write(&up->port, s, count, ip22zilog_put_char); udelay(2); spin_unlock_irqrestore(&up->port.lock, flags); } diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c index 242a041..876bc5e 100644 --- a/drivers/serial/m32r_sio.c +++ b/drivers/serial/m32r_sio.c @@ -1039,6 +1039,14 @@ static inline void wait_for_xmitr(struct uart_sio_port *up) } } +static void m32r_sio_console_putchar(struct uart_port *port, int ch) +{ + struct uart_sio_port *up = (struct uart_sio_port *)port; + + wait_for_xmitr(up); + sio_out(up, SIOTXB, ch); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -1058,23 +1066,7 @@ static void m32r_sio_console_write(struct console *co, const char *s, ier = sio_in(up, SIOTRCR); sio_out(up, SIOTRCR, 0); - /* - * Now, do each character - */ - for (i = 0; i < count; i++, s++) { - wait_for_xmitr(up); - - /* - * Send the character out. - * If a LF, also do CR... - */ - sio_out(up, SIOTXB, *s); - - if (*s == 10) { - wait_for_xmitr(up); - sio_out(up, SIOTXB, 13); - } - } + uart_console_write(&up->port, s, count, m32r_sio_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 61dd17d..928e6cf 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -603,15 +603,14 @@ mpc52xx_console_write(struct console *co, const char *s, unsigned int count) udelay(1); /* Write all the chars */ - for ( i=0 ; i<count ; i++ ) { - - /* Send the char */ - out_8(&psc->mpc52xx_psc_buffer_8, *s); - + for (i = 0; i < count; i++, s++) { /* Line return handling */ - if ( *s++ == '\n' ) + if (*s == '\n') out_8(&psc->mpc52xx_psc_buffer_8, '\r'); + /* Send the char */ + out_8(&psc->mpc52xx_psc_buffer_8, *s); + /* Wait the TX buffer to be empty */ j = 20000; /* Maximum wait */ while (!(in_be16(&psc->mpc52xx_psc_status) & diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index 9b7ed58..513ff85 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c @@ -1916,6 +1916,16 @@ static void __exit exit_pmz(void) #ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE +static void pmz_console_putchar(struct uart_port *port, int ch) +{ + struct uart_pmac_port *uap = (struct uart_pmac_port *)port; + + /* Wait for the transmit buffer to empty. */ + while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0) + udelay(5); + write_zsdata(uap, ch); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -1924,7 +1934,6 @@ static void pmz_console_write(struct console *con, const char *s, unsigned int c { struct uart_pmac_port *uap = &pmz_ports[con->index]; unsigned long flags; - int i; if (ZS_IS_ASLEEP(uap)) return; @@ -1934,17 +1943,7 @@ static void pmz_console_write(struct console *con, const char *s, unsigned int c write_zsreg(uap, R1, uap->curregs[1] & ~TxINT_ENAB); write_zsreg(uap, R5, uap->curregs[5] | TxENABLE | RTS | DTR); - for (i = 0; i < count; i++) { - /* Wait for the transmit buffer to empty. */ - while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0) - udelay(5); - write_zsdata(uap, s[i]); - if (s[i] == 10) { - while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0) - udelay(5); - write_zsdata(uap, R13); - } - } + uart_console_write(&uap->port, s, count, pmz_console_putchar); /* Restore the values in the registers. */ write_zsreg(uap, R1, uap->curregs[1]); diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index 10535f0..77d4568 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -619,6 +619,14 @@ static inline void wait_for_xmitr(struct uart_pxa_port *up) } } +static void serial_pxa_console_putchar(struct uart_port *port, int ch) +{ + struct uart_pxa_port *up = (struct uart_pxa_port *)port; + + wait_for_xmitr(up); + serial_out(up, UART_TX, ch); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -630,7 +638,6 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count) { struct uart_pxa_port *up = &serial_pxa_ports[co->index]; unsigned int ier; - int i; /* * First save the IER then disable the interrupts @@ -638,22 +645,7 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count) ier = serial_in(up, UART_IER); serial_out(up, UART_IER, UART_IER_UUE); - /* - * Now, do each character - */ - for (i = 0; i < count; i++, s++) { - wait_for_xmitr(up); - - /* - * Send the character out. - * If a LF, also do CR... - */ - serial_out(up, UART_TX, *s); - if (*s == 10) { - wait_for_xmitr(up); - serial_out(up, UART_TX, 13); - } - } + uart_console_write(&up->port, s, count, serial_pxa_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index 00d7c0a..f5aac92 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c @@ -1586,25 +1586,19 @@ s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon) } static void -s3c24xx_serial_console_write(struct console *co, const char *s, - unsigned int count) +s3c24xx_serial_console_putchar(struct uart_port *port, int ch) { - int i; unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON); + while (!s3c24xx_serial_console_txrdy(port, ufcon)) + barrier(); + wr_regb(cons_uart, S3C2410_UTXH, ch); +} - for (i = 0; i < count; i++) { - while (!s3c24xx_serial_console_txrdy(cons_uart, ufcon)) - barrier(); - - wr_regb(cons_uart, S3C2410_UTXH, s[i]); - - if (s[i] == '\n') { - while (!s3c24xx_serial_console_txrdy(cons_uart, ufcon)) - barrier(); - - wr_regb(cons_uart, S3C2410_UTXH, '\r'); - } - } +static void +s3c24xx_serial_console_write(struct console *co, const char *s, + unsigned int count) +{ + uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar); } static void __init diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index 2c00b86..c2d9068 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c @@ -689,6 +689,14 @@ void __init sa1100_register_uart(int idx, int port) #ifdef CONFIG_SERIAL_SA1100_CONSOLE +static void sa1100_console_putchar(struct uart_port *port, int ch) +{ + struct sa1100_port *sport = (struct sa1100_port *)port; + + while (!(UART_GET_UTSR1(sport) & UTSR1_TNF)) + barrier(); + UART_PUT_CHAR(sport, ch); +} /* * Interrupts are disabled on entering @@ -697,7 +705,7 @@ static void sa1100_console_write(struct console *co, const char *s, unsigned int count) { struct sa1100_port *sport = &sa1100_ports[co->index]; - unsigned int old_utcr3, status, i; + unsigned int old_utcr3, status; /* * First, save UTCR3 and then disable interrupts @@ -706,21 +714,7 @@ sa1100_console_write(struct console *co, const char *s, unsigned int count) UART_PUT_UTCR3(sport, (old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)) | UTCR3_TXE); - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - do { - status = UART_GET_UTSR1(sport); - } while (!(status & UTSR1_TNF)); - UART_PUT_CHAR(sport, s[i]); - if (s[i] == '\n') { - do { - status = UART_GET_UTSR1(sport); - } while (!(status & UTSR1_TNF)); - UART_PUT_CHAR(sport, '\r'); - } - } + uart_console_write(&sport->port, s, count, sa1100_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index cc1faa3..fcd7744 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1755,6 +1755,27 @@ static int uart_read_proc(char *page, char **start, off_t off, #ifdef CONFIG_SERIAL_CORE_CONSOLE /* + * uart_console_write - write a console message to a serial port + * @port: the port to write the message + * @s: array of characters + * @count: number of characters in string to write + * @write: function to write character to port + */ +void uart_console_write(struct uart_port *port, const char *s, + unsigned int count, + void (*putchar)(struct uart_port *, int)) +{ + unsigned int i; + + for (i = 0; i < count; i++, s++) { + if (*s == '\n') + putchar(port, '\r'); + putchar(port, *s); + } +} +EXPORT_SYMBOL_GPL(uart_console_write); + +/* * Check whether an invalid uart number has been specified, and * if so, search for the first available port that does have * console support. diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c index 04186ea..aa521b8 100644 --- a/drivers/serial/serial_lh7a40x.c +++ b/drivers/serial/serial_lh7a40x.c @@ -543,6 +543,12 @@ static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = { #else # define LH7A40X_CONSOLE &lh7a40x_console +static void lh7a40xuart_console_putchar(struct uart_port *port, int ch) +{ + while (UR(port, UART_R_STATUS) & nTxRdy) + ; + UR(port, UART_R_DATA) = ch; +} static void lh7a40xuart_console_write (struct console* co, const char* s, @@ -556,16 +562,7 @@ static void lh7a40xuart_console_write (struct console* co, UR (port, UART_R_INTEN) = 0; /* Disable all interrupts */ BIT_SET (port, UART_R_CON, UARTEN | SIRDIS); /* Enable UART */ - for (; count-- > 0; ++s) { - while (UR (port, UART_R_STATUS) & nTxRdy) - ; - UR (port, UART_R_DATA) = *s; - if (*s == '\n') { - while ((UR (port, UART_R_STATUS) & TxBusy)) - ; - UR (port, UART_R_DATA) = '\r'; - } - } + uart_console_write(port, s, count, lh7a40xuart_console_putchar); /* Wait until all characters are sent */ while (UR (port, UART_R_STATUS) & TxBusy) diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index 141173e..b848b7d 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c @@ -863,6 +863,14 @@ static inline void wait_for_xmitr(struct uart_txx9_port *up) } } +static void serial_txx9_console_putchar(struct uart_port *port, int ch) +{ + struct uart_txx9_port *up = (struct uart_txx9_port *)port; + + wait_for_xmitr(up); + sio_out(up, TXX9_SITFIFO, ch); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -874,7 +882,6 @@ serial_txx9_console_write(struct console *co, const char *s, unsigned int count) { struct uart_txx9_port *up = &serial_txx9_ports[co->index]; unsigned int ier, flcr; - int i; /* * First save the UER then disable the interrupts @@ -888,22 +895,7 @@ serial_txx9_console_write(struct console *co, const char *s, unsigned int count) if (!(up->port.flags & UPF_CONS_FLOW) && (flcr & TXX9_SIFLCR_TES)) sio_out(up, TXX9_SIFLCR, flcr & ~TXX9_SIFLCR_TES); - /* - * Now, do each character - */ - for (i = 0; i < count; i++, s++) { - wait_for_xmitr(up); - - /* - * Send the character out. - * If a LF, also do CR... - */ - sio_out(up, TXX9_SITFIFO, *s); - if (*s == 10) { - wait_for_xmitr(up); - sio_out(up, TXX9_SITFIFO, 13); - } - } + uart_console_write(&up->port, s, count, serial_txx9_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index a2fb0c2..bfbe9dc 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -861,8 +861,9 @@ static int num_channels; #ifdef CONFIG_SERIAL_SUNSAB_CONSOLE -static __inline__ void sunsab_console_putchar(struct uart_sunsab_port *up, char c) +static void sunsab_console_putchar(struct uart_port *port, int c) { + struct uart_sunsab_port *up = (struct uart_sunsab_port *)port; unsigned long flags; spin_lock_irqsave(&up->port.lock, flags); @@ -876,13 +877,8 @@ static __inline__ void sunsab_console_putchar(struct uart_sunsab_port *up, char static void sunsab_console_write(struct console *con, const char *s, unsigned n) { struct uart_sunsab_port *up = &sunsab_ports[con->index]; - int i; - for (i = 0; i < n; i++) { - if (*s == '\n') - sunsab_console_putchar(up, '\r'); - sunsab_console_putchar(up, *s++); - } + uart_console_write(&up->port, s, n, sunsab_console_putchar); sunsab_tec_wait(up); } diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 46c44b8..7fc3d3b 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1377,6 +1377,14 @@ static __inline__ void wait_for_xmitr(struct uart_sunsu_port *up) } } +static void sunsu_console_putchar(struct uart_port *port, int ch) +{ + struct uart_sunsu_port *up = (struct uart_sunsu_port *)port; + + wait_for_xmitr(up); + serial_out(up, UART_TX, ch); +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -1386,7 +1394,6 @@ static void sunsu_console_write(struct console *co, const char *s, { struct uart_sunsu_port *up = &sunsu_ports[co->index]; unsigned int ier; - int i; /* * First save the UER then disable the interrupts @@ -1394,22 +1401,7 @@ static void sunsu_console_write(struct console *co, const char *s, ier = serial_in(up, UART_IER); serial_out(up, UART_IER, 0); - /* - * Now, do each character - */ - for (i = 0; i < count; i++, s++) { - wait_for_xmitr(up); - - /* - * Send the character out. - * If a LF, also do CR... - */ - serial_out(up, UART_TX, *s); - if (*s == 10) { - wait_for_xmitr(up); - serial_out(up, UART_TX, 13); - } - } + uart_console_write(&up->port, s, count, sunsu_console_putchar); /* * Finally, wait for transmitter to become empty diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index 10b35c6..cd49ebb 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -1252,8 +1252,9 @@ static struct zilog_layout __iomem * __init get_zs(int chip, int node) #define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */ -static void sunzilog_put_char(struct zilog_channel __iomem *channel, unsigned char ch) +static void sunzilog_putchar(struct uart_port *port, int ch) { + struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); int loops = ZS_PUT_CHAR_MAX_DELAY; /* This is a timed polling loop so do not switch the explicit @@ -1284,7 +1285,7 @@ static int sunzilog_serio_write(struct serio *serio, unsigned char ch) spin_lock_irqsave(&sunzilog_serio_lock, flags); - sunzilog_put_char(ZILOG_CHANNEL_FROM_PORT(&up->port), ch); + sunzilog_putchar(&up->port, ch); spin_unlock_irqrestore(&sunzilog_serio_lock, flags); @@ -1325,16 +1326,10 @@ static void sunzilog_console_write(struct console *con, const char *s, unsigned int count) { struct uart_sunzilog_port *up = &sunzilog_port_table[con->index]; - struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(&up->port); unsigned long flags; - int i; spin_lock_irqsave(&up->port.lock, flags); - for (i = 0; i < count; i++, s++) { - sunzilog_put_char(channel, *s); - if (*s == 10) - sunzilog_put_char(channel, 13); - } + uart_console_write(&up->port, s, count, sunzilog_putchar); udelay(2); spin_unlock_irqrestore(&up->port.lock, flags); } diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c index bd62941..df5e871 100644 --- a/drivers/serial/vr41xx_siu.c +++ b/drivers/serial/vr41xx_siu.c @@ -821,25 +821,23 @@ static void wait_for_xmitr(struct uart_port *port) } } +static void siu_console_putchar(struct uart_port *port, int ch) +{ + wait_for_xmitr(port); + siu_write(port, UART_TX, ch); +} + static void siu_console_write(struct console *con, const char *s, unsigned count) { struct uart_port *port; uint8_t ier; - unsigned i; port = &siu_uart_ports[con->index]; ier = siu_read(port, UART_IER); siu_write(port, UART_IER, 0); - for (i = 0; i < count && *s != '\0'; i++, s++) { - wait_for_xmitr(port); - siu_write(port, UART_TX, *s); - if (*s == '\n') { - wait_for_xmitr(port); - siu_write(port, UART_TX, '\r'); - } - } + uart_console_write(port, s, count, siu_console_putchar); wait_for_xmitr(port); siu_write(port, UART_IER, ier); |