From 37b91f25b06a36bee3468ecc3db1da5f71c05f1e Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sat, 10 Jan 2004 04:34:27 -0500 Subject: [PATCH] (1/12) Probe2 infrastructure for 2.6 experimental New infrastructure to allow probing older builtin drivers (like ISA) Originally by Al Viro, updated to apply agains jgarzik/net-drivers-2.5-exp --- include/linux/netdevice.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 666d89f875f5..9940159f5cf7 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -496,6 +496,7 @@ extern rwlock_t dev_base_lock; /* Device list lock */ extern int netdev_boot_setup_add(char *name, struct ifmap *map); extern int netdev_boot_setup_check(struct net_device *dev); +extern unsigned long netdev_boot_base(const char *prefix, int unit); extern struct net_device *dev_getbyhwaddr(unsigned short type, char *hwaddr); extern struct net_device *__dev_getfirstbyhwtype(unsigned short type); extern struct net_device *dev_getfirstbyhwtype(unsigned short type); -- cgit v1.2.3 From 1d07e29ec6cc6e5d1ffd59bfe8f85b3b64650bf0 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sat, 10 Jan 2004 04:55:45 -0500 Subject: [PATCH] (20/42) hp100-T10 NE44-hp100 * convert to dynamic allocation * use device model for PCI and EISA * use pci id's to find PCI devices * fix missing id's for 10 Mbit only PCI boards --- drivers/net/Space.c | 11 +- drivers/net/hp100.c | 741 +++++++++++++++++++++++++----------------------- include/linux/pci_ids.h | 2 + 3 files changed, 394 insertions(+), 360 deletions(-) (limited to 'include/linux') diff --git a/drivers/net/Space.c b/drivers/net/Space.c index 31e1ee40c907..0cfa6e7bbb01 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -41,7 +41,7 @@ */ extern int ne2_probe(struct net_device *dev); -extern int hp100_probe(struct net_device *dev); +extern struct net_device *hp100_probe(int unit); extern struct net_device *ultra_probe(int unit); extern int ultra32_probe(struct net_device *dev); extern struct net_device *wd_probe(int unit); @@ -197,14 +197,10 @@ static struct devprobe mca_probes[] __initdata = { * ISA probes that touch addresses < 0x400 (including those that also * look for EISA/PCI/MCA cards in addition to ISA cards). */ -static struct devprobe isa_probes[] __initdata = { +static struct devprobe2 isa_probes2[] __initdata = { #ifdef CONFIG_HP100 /* ISA, EISA & PCI */ {hp100_probe, 0}, #endif - {NULL, 0}, -}; - -static struct devprobe2 isa_probes2[] __initdata = { #ifdef CONFIG_3C515 {tc515_probe, 0}, #endif @@ -382,8 +378,7 @@ static int __init ethif_probe(int unit) if (probe_list(dev, m68k_probes) == 0 || probe_list(dev, mips_probes) == 0 || probe_list(dev, eisa_probes) == 0 || - probe_list(dev, mca_probes) == 0 || - probe_list(dev, isa_probes) == 0) + probe_list(dev, mca_probes) == 0) err = register_netdev(dev); if (err) diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index f92d5c9b5780..e30346beb412 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -118,8 +118,6 @@ #include #include -typedef struct net_device_stats hp100_stats_t; - #include "hp100.h" /* @@ -130,23 +128,8 @@ typedef struct net_device_stats hp100_stats_t; #define HP100_BUS_EISA 1 #define HP100_BUS_PCI 2 -#ifndef PCI_DEVICE_ID_HP_J2585B -#define PCI_DEVICE_ID_HP_J2585B 0x1031 -#endif -#ifndef PCI_VENDOR_ID_COMPEX -#define PCI_VENDOR_ID_COMPEX 0x11f6 -#endif -#ifndef PCI_DEVICE_ID_COMPEX_ENET100VG4 -#define PCI_DEVICE_ID_COMPEX_ENET100VG4 0x0112 -#endif -#ifndef PCI_VENDOR_ID_COMPEX2 -#define PCI_VENDOR_ID_COMPEX2 0x101a -#endif -#ifndef PCI_DEVICE_ID_COMPEX2_100VG -#define PCI_DEVICE_ID_COMPEX2_100VG 0x0005 -#endif - #define HP100_REGION_SIZE 0x20 /* for ioports */ +#define HP100_SIG_LEN 8 /* same as EISA_SIG_LEN */ #define HP100_MAX_PACKET_SIZE (1536+4) #define HP100_MIN_PACKET_SIZE 60 @@ -165,20 +148,9 @@ typedef struct net_device_stats hp100_stats_t; * structures */ -struct hp100_eisa_id { - u_int id; - const char *name; - u_char bus; -}; - -struct hp100_pci_id { - u_short vendor; - u_short device; -}; - struct hp100_private { - struct hp100_eisa_id *id; spinlock_t lock; + char id[HP100_SIG_LEN]; u_short chip; u_short soft_model; u_int memory_size; @@ -196,7 +168,7 @@ struct hp100_private { u_char mac1_mode; u_char mac2_mode; u_char hash_bytes[8]; - hp100_stats_t stats; + struct net_device_stats stats; /* Rings for busmaster mode: */ hp100_ring_t *rxrhead; /* Head (oldest) index into rxring */ @@ -216,83 +188,36 @@ struct hp100_private { /* * variables */ - -static struct hp100_eisa_id hp100_eisa_ids[] = { - - /* 10/100 EISA card with revision A Cascade chip */ - {0x80F1F022, "HP J2577 rev A", HP100_BUS_EISA}, - - /* 10/100 ISA card with revision A Cascade chip */ - {0x50F1F022, "HP J2573 rev A", HP100_BUS_ISA}, - - /* 10 only EISA card with Cascade chip */ - {0x2019F022, "HP 27248B", HP100_BUS_EISA}, - - /* 10/100 EISA card with Cascade chip */ - {0x4019F022, "HP J2577", HP100_BUS_EISA}, - - /* 10/100 ISA card with Cascade chip */ - {0x5019F022, "HP J2573", HP100_BUS_ISA}, - - /* 10/100 EISA card with AT&T chip */ - {0x9019f022, "HP J2577", HP100_BUS_EISA }, - - /* 10/100 PCI card - old J2585A */ - {0x1030103c, "HP J2585A", HP100_BUS_PCI}, - - /* 10/100 PCI card - new J2585B - master capable */ - {0x1041103c, "HP J2585B", HP100_BUS_PCI}, - - /* 10 Mbit Combo Adapter */ - {0x1042103c, "HP J2970", HP100_BUS_PCI}, - - /* 10 Mbit 10baseT Adapter */ - {0x1040103c, "HP J2973", HP100_BUS_PCI}, - - /* 10/100 EISA card from Compex */ - {0x0103180e, "ReadyLink ENET100-VG4", HP100_BUS_EISA}, - - /* 10/100 EISA card from Compex - FreedomLine (sq5bpf) */ - /* Note: plhbrod@mbox.vol.cz reported that same ID have ISA */ - /* version of adapter, too... */ - {0x0104180e, "FreedomLine 100/VG", HP100_BUS_EISA}, - - /* 10/100 PCI card from Compex - FreedomLine - * - * I think this card doesn't like aic7178 scsi controller, but - * I haven't tested this much. It works fine on diskless machines. - * Jacek Lipkowski - */ - {0x021211f6, "FreedomLine 100/VG", HP100_BUS_PCI}, - - /* 10/100 PCI card from Compex (J2585A compatible) */ - {0x011211f6, "ReadyLink ENET100-VG4", HP100_BUS_PCI}, - - /* 10/100 PCI card from KTI */ - {0x40008e2e, "KTI DP-200", HP100_BUS_PCI } +static const char *hp100_isa_tbl[] = { + "HWPF150", /* HP J2573 rev A */ + "HWP1950", /* HP J2573 */ }; -#define HP100_EISA_IDS_SIZE (sizeof(hp100_eisa_ids)/sizeof(struct hp100_eisa_id)) - -#ifdef CONFIG_PCI -static struct hp100_pci_id hp100_pci_ids[] = { - {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585A}, - {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585B}, - {PCI_VENDOR_ID_COMPEX, PCI_DEVICE_ID_COMPEX_ENET100VG4}, - {PCI_VENDOR_ID_COMPEX2, PCI_DEVICE_ID_COMPEX2_100VG} +#ifdef CONFIG_EISA +static struct eisa_device_id hp100_eisa_tbl[] = { + { "HWPF180" }, /* HP J2577 rev A */ + { "HWP1920" }, /* HP 27248B */ + { "HWP1940" }, /* HP J2577 */ + { "HWP1990" }, /* HP J2577 */ + { "CPX0301" }, /* ReadyLink ENET100-VG4 */ + { "CPX0401" }, /* FreedomLine 100/VG */ }; +MODULE_DEVICE_TABLE(eisa, hp100_eisa_tbl); #endif -#define HP100_PCI_IDS_SIZE (sizeof(hp100_pci_ids)/sizeof(struct hp100_pci_id)) - +#ifdef CONFIG_PCI static struct pci_device_id hp100_pci_tbl[] = { {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585A, PCI_ANY_ID, PCI_ANY_ID,}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585B, PCI_ANY_ID, PCI_ANY_ID,}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2970A, PCI_ANY_ID, PCI_ANY_ID,}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2973A, PCI_ANY_ID, PCI_ANY_ID,}, {PCI_VENDOR_ID_COMPEX, PCI_DEVICE_ID_COMPEX_ENET100VG4, PCI_ANY_ID, PCI_ANY_ID,}, {PCI_VENDOR_ID_COMPEX2, PCI_DEVICE_ID_COMPEX2_100VG, PCI_ANY_ID, PCI_ANY_ID,}, +/* {PCI_VENDOR_ID_KTI, PCI_DEVICE_ID_KTI_DP200, PCI_ANY_ID, PCI_ANY_ID }, */ {} /* Terminating entry */ }; MODULE_DEVICE_TABLE(pci, hp100_pci_tbl); +#endif static int hp100_rx_ratio = HP100_DEFAULT_RX_RATIO; static int hp100_priority_tx = HP100_DEFAULT_PRIORITY_TX; @@ -316,7 +241,7 @@ static int hp100_start_xmit(struct sk_buff *skb, struct net_device *dev); static int hp100_start_xmit_bm(struct sk_buff *skb, struct net_device *dev); static void hp100_rx(struct net_device *dev); -static hp100_stats_t *hp100_get_stats(struct net_device *dev); +static struct net_device_stats *hp100_get_stats(struct net_device *dev); static void hp100_misc_interrupt(struct net_device *dev); static void hp100_update_stats(struct net_device *dev); static void hp100_clear_stats(struct hp100_private *lp, int ioaddr); @@ -370,196 +295,180 @@ static void wait(void) * since this could cause problems when the card is not installed. */ -int __init hp100_probe(struct net_device *dev) +/* + * Read board id and convert to string. + * Effectively same code as decode_eisa_sig + */ +static __init const char *hp100_read_id(int ioaddr) { - int base_addr = dev ? dev->base_addr : 0; - int ioaddr = 0; - int pci_start_index = 0; + int i; + static char str[HP100_SIG_LEN]; + unsigned char sig[4], sum; + unsigned short rev; -#ifdef HP100_DEBUG_B - hp100_outw(0x4200, TRACE); - printk("hp100: %s: probe\n", dev->name); -#endif + hp100_page(ID_MAC_ADDR); + sum = 0; + for (i = 0; i < 4; i++) { + sig[i] = hp100_inb(BOARD_ID + i); + sum += sig[i]; + } - if (base_addr > 0xff) { /* Check a single specified location. */ - if (check_region(base_addr, HP100_REGION_SIZE)) - return -EINVAL; - if (base_addr < 0x400) - return hp100_probe1(dev, base_addr, HP100_BUS_ISA, - NULL); - if (EISA_bus && base_addr >= 0x1c38 && ((base_addr - 0x1c38) & 0x3ff) == 0) - return hp100_probe1(dev, base_addr, HP100_BUS_EISA, NULL); -#ifdef CONFIG_PCI - printk("hp100: %s: You must specify card # in i/o address parameter for PCI bus...", dev->name); -#else - return -ENODEV; -#endif - } else -#ifdef CONFIG_PCI - if (base_addr > 0 && base_addr < 8 + 1) - pci_start_index = 0x100 | (base_addr - 1); - else -#endif - if (base_addr != 0) - return -ENXIO; + sum += hp100_inb(BOARD_ID + i); + if (sum != 0xff) + return NULL; /* bad checksum */ - /* First: scan PCI bus(es) */ + str[0] = ((sig[0] >> 2) & 0x1f) + ('A' - 1); + str[1] = (((sig[0] & 3) << 3) | (sig[1] >> 5)) + ('A' - 1); + str[2] = (sig[1] & 0x1f) + ('A' - 1); + rev = (sig[2] << 8) | sig[3]; + sprintf(str + 3, "%04X", rev); + + return str; +} + +static __init int hp100_isa_probe1(struct net_device *dev, int addr) +{ + const char *sig; + int i; + + if (!request_region(addr, HP100_REGION_SIZE, "hp100")) + goto err; + + sig = hp100_read_id(addr); + release_region(addr, HP100_REGION_SIZE); + + if (sig == NULL) + goto err; + + for (i = 0; i < ARRAY_SIZE(hp100_isa_tbl); i++) { + if (!strcmp(hp100_isa_tbl[i], sig)) + break; -#ifdef CONFIG_PCI - { - int pci_index; - struct pci_dev *pci_dev = NULL; - int pci_id_index; - u_short pci_command; - -#ifdef HP100_DEBUG_PCI - printk("hp100: %s: PCI BIOS is present, checking for devices..\n", dev->name); -#endif - pci_index = 0; - for (pci_id_index = 0; pci_id_index < HP100_PCI_IDS_SIZE; - pci_id_index++) { - while ((pci_dev = pci_find_device(hp100_pci_ids[pci_id_index].vendor, - hp100_pci_ids[pci_id_index].device, - pci_dev)) != NULL) { - if (pci_index < (pci_start_index & 7)) { - pci_index++; - continue; - } - if (pci_enable_device(pci_dev)) - continue; - /* found... */ - ioaddr = pci_resource_start(pci_dev, 0); - if (check_region(ioaddr, HP100_REGION_SIZE)) - continue; - pci_read_config_word(pci_dev, PCI_COMMAND, &pci_command); - if (!(pci_command & PCI_COMMAND_IO)) { -#ifdef HP100_DEBUG - printk("hp100: %s: PCI I/O Bit has not been set. Setting...\n", dev->name); -#endif - pci_command |= PCI_COMMAND_IO; - pci_write_config_word(pci_dev, PCI_COMMAND, pci_command); - } - if (!(pci_command & PCI_COMMAND_MASTER)) { -#ifdef HP100_DEBUG - printk("hp100: %s: PCI Master Bit has not been set. Setting...\n", dev->name); -#endif - pci_command |= PCI_COMMAND_MASTER; - pci_write_config_word(pci_dev, PCI_COMMAND, pci_command); - } -#ifdef HP100_DEBUG - printk("hp100: %s: PCI adapter found at 0x%x\n", dev->name, ioaddr); -#endif - if (hp100_probe1(dev, ioaddr, HP100_BUS_PCI, pci_dev) == 0) - return 0; - } - } } - if (pci_start_index > 0) - return -ENODEV; -#endif /* CONFIG_PCI */ - /* Second: Probe all EISA possible port regions (if EISA bus present) */ - for (ioaddr = 0x1c38; EISA_bus && ioaddr < 0x10000; ioaddr += 0x400) { - if (check_region(ioaddr, HP100_REGION_SIZE)) - continue; - if (hp100_probe1(dev, ioaddr, HP100_BUS_EISA, NULL) == 0) - return 0; + if (i < ARRAY_SIZE(hp100_isa_tbl)) + return hp100_probe1(dev, addr, HP100_BUS_ISA, NULL); + err: + return -ENODEV; + +} +/* + * Probe for ISA board. + * EISA and PCI are handled by device infrastructure. + */ + +static int __init hp100_isa_probe(struct net_device *dev, int addr) +{ + int err = -ENODEV; + + /* Probe for a specific ISA address */ + if (addr > 0xff && addr < 0x400) + err = hp100_isa_probe1(dev, addr); + + else if (addr != 0) + err = -ENXIO; + + else { + /* Probe all ISA possible port regions */ + for (addr = 0x100; addr < 0x400; addr += 0x20) { + err = hp100_isa_probe1(dev, addr); + if (!err) + break; + } } + return err; +} - /* Third: Probe all ISA possible port regions */ - for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x20) { - if (check_region(ioaddr, HP100_REGION_SIZE)) - continue; - if (hp100_probe1(dev, ioaddr, HP100_BUS_ISA, NULL) == 0) - return 0; + +struct net_device * __init hp100_probe(int unit) +{ + struct net_device *dev = alloc_etherdev(sizeof(struct hp100_private)); + int err; + + if (!dev) + return ERR_PTR(-ENODEV); + + SET_MODULE_OWNER(dev); + +#ifdef HP100_DEBUG_B + hp100_outw(0x4200, TRACE); + printk("hp100: %s: probe\n", dev->name); +#endif + + if (unit >= 0) { + sprintf(dev->name, "eth%d", unit); + netdev_boot_setup_check(dev); } - return -ENODEV; + err = hp100_isa_probe(dev, dev->base_addr); + if (err) + goto out; + + err = register_netdev(dev); + if (err) + goto out1; + return dev; + out1: + release_region(dev->base_addr, HP100_REGION_SIZE); + out: + free_netdev(dev); + return ERR_PTR(err); } static int __init hp100_probe1(struct net_device *dev, int ioaddr, u_char bus, struct pci_dev *pci_dev) { int i; - - u_char uc, uc_1; - u_int eisa_id; + int err = -ENODEV; + const char *eid; u_int chip; + u_char uc; u_int memory_size = 0, virt_memory_size = 0; u_short local_mode, lsw; short mem_mapped; unsigned long mem_ptr_phys; void **mem_ptr_virt; struct hp100_private *lp; - struct hp100_eisa_id *eid; #ifdef HP100_DEBUG_B hp100_outw(0x4201, TRACE); printk("hp100: %s: probe1\n", dev->name); #endif - if (dev == NULL) { -#ifdef HP100_DEBUG - printk("hp100_probe1: %s: dev == NULL ?\n", dev->name); -#endif - return -EIO; - } + /* memory region for programmed i/o */ + if (!request_region(ioaddr, HP100_REGION_SIZE, "hp100")) + goto out1; - if (hp100_inw(HW_ID) != HP100_HW_ID_CASCADE) { - return -ENODEV; - } else { - chip = hp100_inw(PAGING) & HP100_CHIPID_MASK; + if (hp100_inw(HW_ID) != HP100_HW_ID_CASCADE) + goto out2; + + chip = hp100_inw(PAGING) & HP100_CHIPID_MASK; #ifdef HP100_DEBUG - if (chip == HP100_CHIPID_SHASTA) - printk("hp100: %s: Shasta Chip detected. (This is a pre 802.12 chip)\n", dev->name); - else if (chip == HP100_CHIPID_RAINIER) - printk("hp100: %s: Rainier Chip detected. (This is a pre 802.12 chip)\n", dev->name); - else if (chip == HP100_CHIPID_LASSEN) - printk("hp100: %s: Lassen Chip detected.\n", dev->name); - else - printk("hp100: %s: Warning: Unknown CASCADE chip (id=0x%.4x).\n", dev->name, chip); + if (chip == HP100_CHIPID_SHASTA) + printk("hp100: %s: Shasta Chip detected. (This is a pre 802.12 chip)\n", dev->name); + else if (chip == HP100_CHIPID_RAINIER) + printk("hp100: %s: Rainier Chip detected. (This is a pre 802.12 chip)\n", dev->name); + else if (chip == HP100_CHIPID_LASSEN) + printk("hp100: %s: Lassen Chip detected.\n", dev->name); + else + printk("hp100: %s: Warning: Unknown CASCADE chip (id=0x%.4x).\n", dev->name, chip); #endif - } dev->base_addr = ioaddr; - hp100_page(ID_MAC_ADDR); - for (i = uc = eisa_id = 0; i < 4; i++) { - eisa_id >>= 8; - uc_1 = hp100_inb(BOARD_ID + i); - eisa_id |= uc_1 << 24; - uc += uc_1; - } - uc += hp100_inb(BOARD_ID + 4); - - if (uc != 0xff) { /* bad checksum? */ - printk("hp100_probe: %s: bad EISA ID checksum at base port 0x%x\n", dev->name, ioaddr); - return -ENODEV; - } - - for (i = 0; i < HP100_EISA_IDS_SIZE; i++) - if (hp100_eisa_ids[i].id == eisa_id) - break; - if (i >= HP100_EISA_IDS_SIZE) { - for (i = 0; i < HP100_EISA_IDS_SIZE; i++) - if ((hp100_eisa_ids[i].id & 0xf0ffffff) == (eisa_id & 0xf0ffffff)) - break; - if (i >= HP100_EISA_IDS_SIZE) { - printk ("hp100_probe: %s: card at port 0x%x isn't known (id = 0x%x)\n", dev->name, ioaddr, eisa_id); - return -ENODEV; - } - } - eid = &hp100_eisa_ids[i]; - if ((eid->id & 0x0f000000) < (eisa_id & 0x0f000000)) { - printk("hp100_probe: %s: newer version of card %s at port 0x%x - unsupported\n", dev->name, eid->name, ioaddr); - return -ENODEV; + eid = hp100_read_id(ioaddr); + if (eid == NULL) { /* bad checksum? */ + printk(KERN_WARNING "hp100_probe: bad ID checksum at base port 0x%x\n", ioaddr); + goto out2; } + hp100_page(ID_MAC_ADDR); for (i = uc = 0; i < 7; i++) uc += hp100_inb(LAN_ADDR + i); if (uc != 0xff) { - printk("hp100_probe: %s: bad lan address checksum (card %s at port 0x%x)\n", dev->name, eid->name, ioaddr); - return -EIO; + printk(KERN_WARNING "hp100_probe: bad lan address checksum at port 0x%x)\n", ioaddr); + err = -EIO; + goto out2; } /* Make sure, that all registers are correctly updated... */ @@ -607,17 +516,17 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr, hp100_outw(HP100_MEM_EN | HP100_RESET_LB, OPTION_LSW); hp100_outw(HP100_IO_EN | HP100_SET_LB, OPTION_LSW); hp100_outw(HP100_BM_WRITE | HP100_BM_READ | HP100_RESET_HB, OPTION_LSW); - printk("hp100: %s: IO mapped mode forced.\n", dev->name); + printk("hp100: IO mapped mode forced.\n"); } else if (local_mode == 2) { hp100_outw(HP100_MEM_EN | HP100_SET_LB, OPTION_LSW); hp100_outw(HP100_IO_EN | HP100_SET_LB, OPTION_LSW); hp100_outw(HP100_BM_WRITE | HP100_BM_READ | HP100_RESET_HB, OPTION_LSW); - printk("hp100: %s: Shared memory mode requested.\n", dev->name); + printk("hp100: Shared memory mode requested.\n"); } else if (local_mode == 4) { if (chip == HP100_CHIPID_LASSEN) { hp100_outw(HP100_BM_WRITE | HP100_BM_READ | HP100_SET_HB, OPTION_LSW); hp100_outw(HP100_IO_EN | HP100_MEM_EN | HP100_RESET_LB, OPTION_LSW); - printk("hp100: %s: Busmaster mode requested.\n", dev->name); + printk("hp100: Busmaster mode requested.\n"); } local_mode = 1; } @@ -643,7 +552,7 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr, /* Gracefully fallback to shared memory */ goto busmasterfail; } - printk("hp100: %s: Busmaster mode enabled.\n", dev->name); + printk("hp100: Busmaster mode enabled.\n"); hp100_outw(HP100_MEM_EN | HP100_IO_EN | HP100_RESET_LB, OPTION_LSW); } else { busmasterfail: @@ -675,7 +584,7 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr, mem_ptr_phys &= ~0x1fff; /* 8k alignment */ if (bus == HP100_BUS_ISA && (mem_ptr_phys & ~0xfffff) != 0) { - printk("hp100: %s: Can only use programmed i/o mode.\n", dev->name); + printk("hp100: Can only use programmed i/o mode.\n"); mem_ptr_phys = 0; mem_mapped = 0; local_mode = 3; /* Use programmed i/o */ @@ -699,7 +608,7 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr, } if (mem_ptr_virt == NULL) { /* all ioremap tries failed */ - printk("hp100: %s: Failed to ioremap the PCI card memory. Will have to use i/o mapped mode.\n", dev->name); + printk("hp100: Failed to ioremap the PCI card memory. Will have to use i/o mapped mode.\n"); local_mode = 3; virt_memory_size = 0; } @@ -710,17 +619,14 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr, mem_mapped = 0; mem_ptr_phys = 0; mem_ptr_virt = NULL; - printk("hp100: %s: Using (slow) programmed i/o mode.\n", dev->name); + printk("hp100: Using (slow) programmed i/o mode.\n"); } /* Initialise the "private" data structure for this card. */ - if ((dev->priv = kmalloc(sizeof(struct hp100_private), GFP_KERNEL)) == NULL) - return -ENOMEM; - lp = (struct hp100_private *) dev->priv; - memset(lp, 0, sizeof(struct hp100_private)); + spin_lock_init(&lp->lock); - lp->id = eid; + strlcpy(lp->id, eid, HP100_SIG_LEN); lp->chip = chip; lp->mode = local_mode; lp->bus = bus; @@ -741,9 +647,6 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr, lp->virt_memory_size = virt_memory_size; lp->rx_ratio = hp100_rx_ratio; /* can be conf'd with insmod */ - /* memory region for programmed i/o */ - request_region(dev->base_addr, HP100_REGION_SIZE, eid->name); - dev->open = hp100_open; dev->stop = hp100_close; @@ -776,10 +679,6 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr, /* Reset statistics (counters) */ hp100_clear_stats(lp, ioaddr); - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pci_dev->dev); - ether_setup(dev); - /* If busmaster mode is wanted, a dma-capable memory area is needed for * the rx and tx PDLs * PCI cards can access the whole PC memory. Therefore GFP_DMA is not @@ -795,8 +694,10 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr, /* Conversion to new PCI API : * Pages are always aligned and zeroed, no need to it ourself. * Doc says should be OK for EISA bus as well - Jean II */ - if ((lp->page_vaddr_algn = pci_alloc_consistent(lp->pci_dev, MAX_RINGSIZE, &page_baddr)) == NULL) - return -ENOMEM; + if ((lp->page_vaddr_algn = pci_alloc_consistent(lp->pci_dev, MAX_RINGSIZE, &page_baddr)) == NULL) { + err = -ENOMEM; + goto out2; + } lp->whatever_offset = ((u_long) page_baddr) - ((u_long) lp->page_vaddr_algn); #ifdef HP100_DEBUG_BM @@ -818,7 +719,7 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr, lp->lan_type = hp100_sense_lan(dev); /* Print out a message what about what we think we have probed. */ - printk("hp100: %s: %s at 0x%x, IRQ %d, ", dev->name, lp->id->name, ioaddr, dev->irq); + printk("hp100: at 0x%x, IRQ %d, ", ioaddr, dev->irq); switch (bus) { case HP100_BUS_EISA: printk("EISA"); @@ -833,7 +734,7 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr, printk(" bus, %dk SRAM (rx/tx %d%%).\n", lp->memory_size >> 10, lp->rx_ratio); if (lp->mode == 2) { /* memory mapped */ - printk("hp100: %s: Memory area at 0x%lx-0x%lx", dev->name, mem_ptr_phys, + printk("hp100: Memory area at 0x%lx-0x%lx", mem_ptr_phys, (mem_ptr_phys + (mem_ptr_phys > 0x100000 ? (u_long) lp->memory_size : 16 * 1024)) - 1); if (mem_ptr_virt) printk(" (virtual base %p)", mem_ptr_virt); @@ -843,7 +744,8 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr, dev->mem_start = mem_ptr_phys; dev->mem_end = mem_ptr_phys + lp->memory_size; } - printk("hp100: %s: ", dev->name); + + printk("hp100: "); if (lp->lan_type != HP100_LAN_ERR) printk("Adapter is attached to "); switch (lp->lan_type) { @@ -861,6 +763,10 @@ static int __init hp100_probe1(struct net_device *dev, int ioaddr, } return 0; +out2: + release_region(ioaddr, HP100_REGION_SIZE); +out1: + return -ENODEV; } /* This procedure puts the card into a stable init state */ @@ -950,6 +856,7 @@ static void hp100_hwinit(struct net_device *dev) /* Finally try to log in the Hub if there may be a VG connection. */ if ((lp->lan_type == HP100_LAN_100) || (lp->lan_type == HP100_LAN_ERR)) hp100_login_to_vg_hub(dev, 0); /* relogin */ + } @@ -1152,7 +1059,7 @@ static int hp100_open(struct net_device *dev) if (request_irq(dev->irq, hp100_interrupt, lp->bus == HP100_BUS_PCI || lp->bus == HP100_BUS_EISA ? SA_SHIRQ : SA_INTERRUPT, - lp->id->name, dev)) { + "hp100", dev)) { printk("hp100: %s: unable to get IRQ %d\n", dev->name, dev->irq); return -EAGAIN; } @@ -2054,7 +1961,7 @@ static void hp100_rx_bm(struct net_device *dev) /* * statistics */ -static hp100_stats_t *hp100_get_stats(struct net_device *dev) +static struct net_device_stats *hp100_get_stats(struct net_device *dev) { unsigned long flags; int ioaddr = dev->base_addr; @@ -2558,10 +2465,14 @@ static int hp100_sense_lan(struct net_device *dev) return HP100_LAN_COAX; } - if ((lp->id->id == 0x02019F022) || - (lp->id->id == 0x01042103c) || (lp->id->id == 0x01040103c)) - return HP100_LAN_ERR; /* Those cards don't have a 100 Mbit connector */ - + /* Those cards don't have a 100 Mbit connector */ + if ( !strcmp(lp->id, "HWP1920") || + (lp->pci_dev && + lp->pci_dev->vendor == PCI_VENDOR_ID && + (lp->pci_dev->device == PCI_DEVICE_ID_HP_J2970A || + lp->pci_dev->device == PCI_DEVICE_ID_HP_J2973A))) + return HP100_LAN_ERR; + if (val_VG & HP100_LINK_CABLE_ST) /* Can hear the HUBs tone. */ return HP100_LAN_100; return HP100_LAN_ERR; @@ -2915,122 +2826,248 @@ void hp100_RegisterDump(struct net_device *dev) #endif +static void cleanup_dev(struct net_device *d) +{ + struct hp100_private *p = (struct hp100_private *) d->priv; + + unregister_netdev(d); + release_region(d->base_addr, HP100_REGION_SIZE); + + if (p->mode == 1) /* busmaster */ + pci_free_consistent(p->pci_dev, MAX_RINGSIZE + 0x0f, + p->page_vaddr_algn, + virt_to_whatever(d, p->page_vaddr_algn)); + if (p->mem_ptr_virt) + iounmap(p->mem_ptr_virt); + + free_netdev(d); +} + +#ifdef CONFIG_EISA +static int __init hp100_eisa_probe (struct device *gendev) +{ + struct net_device *dev = alloc_etherdev(sizeof(struct hp100_private)); + struct eisa_device *edev = to_eisa_device(gendev); + int err; + + if (!dev) + return -ENOMEM; + + SET_MODULE_OWNER(dev); + SET_NETDEV_DEV(dev, &edev->dev); + + err = hp100_probe1(dev, edev->base_addr, HP100_BUS_EISA, NULL); + if (err) + goto out1; + + err = register_netdev(dev); + if (err) + goto out2; + +#ifdef HP100_DEBUG + printk("hp100: %s: EISA adapter found at 0x%x\n", dev->name, + dev->base_addr); +#endif + gendev->driver_data = dev; + return 0; + out2: + release_region(dev->base_addr, HP100_REGION_SIZE); + out1: + free_netdev(dev); + return err; +} + +static int __devexit hp100_eisa_remove (struct device *gendev) +{ + struct net_device *dev = gendev->driver_data; + cleanup_dev(dev); + return 0; +} + +static struct eisa_driver hp100_eisa_driver = { + .id_table = hp100_eisa_tbl, + .driver = { + .name = "hp100", + .probe = hp100_eisa_probe, + .remove = __devexit_p (hp100_eisa_remove), + } +}; +#endif + +#ifdef CONFIG_PCI +static int __devinit hp100_pci_probe (struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct net_device *dev = alloc_etherdev(sizeof(struct hp100_private)); + int ioaddr = pci_resource_start(pdev, 0); + u_short pci_command; + int err; + + if (!dev) + return -ENOMEM; + + SET_MODULE_OWNER(dev); + SET_NETDEV_DEV(dev, &pdev->dev); + + pci_read_config_word(pdev, PCI_COMMAND, &pci_command); + if (!(pci_command & PCI_COMMAND_IO)) { +#ifdef HP100_DEBUG + printk("hp100: %s: PCI I/O Bit has not been set. Setting...\n", dev->name); +#endif + pci_command |= PCI_COMMAND_IO; + pci_write_config_word(pdev, PCI_COMMAND, pci_command); + } + + if (!(pci_command & PCI_COMMAND_MASTER)) { +#ifdef HP100_DEBUG + printk("hp100: %s: PCI Master Bit has not been set. Setting...\n", dev->name); +#endif + pci_command |= PCI_COMMAND_MASTER; + pci_write_config_word(pdev, PCI_COMMAND, pci_command); + } + + + err = hp100_probe1(dev, ioaddr, HP100_BUS_PCI, pdev); + if (err) + goto out1; + err = register_netdev(dev); + if (err) + goto out2; + +#ifdef HP100_DEBUG + printk("hp100: %s: PCI adapter found at 0x%x\n", dev->name, ioaddr); +#endif + pci_set_drvdata(pdev, dev); + return 0; + out2: + release_region(dev->base_addr, HP100_REGION_SIZE); + out1: + free_netdev(dev); + return err; +} + +static void __devexit hp100_pci_remove (struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + + cleanup_dev(dev); +} + + +static struct pci_driver hp100_pci_driver = { + .name = "hp100", + .id_table = hp100_pci_tbl, + .probe = hp100_pci_probe, + .remove = __devexit_p(hp100_pci_remove), +}; +#endif + /* * module section */ -#ifdef MODULE - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jaroslav Kysela , " "Siegfried \"Frieder\" Loeffler (dg1sek) "); MODULE_DESCRIPTION("HP CASCADE Architecture Driver for 100VG-AnyLan Network Adapters"); /* - * Note: if you have more than five 100vg cards in your pc, feel free to - * increase this value - */ - -#define HP100_DEVICES 5 - -/* - * Note: to register three eisa or pci devices, use: + * Note: to register three isa devices, use: * option hp100 hp100_port=0,0,0 * to register one card at io 0x280 as eth239, use: - * option hp100 hp100_port=0x280 hp100_name=eth239 + * option hp100 hp100_port=0x280 */ - +#if defined(MODULE) && defined(CONFIG_ISA) +#define HP100_DEVICES 5 /* Parameters set by insmod */ static int hp100_port[HP100_DEVICES] = { 0, [1 ... (HP100_DEVICES-1)] = -1 }; MODULE_PARM(hp100_port, "1-" __MODULE_STRING(HP100_DEVICES) "i"); -/* Allocate HP100_DEVICES strings of length IFNAMSIZ, one string for each device */ -static char hp100_name[HP100_DEVICES][IFNAMSIZ] = { "", "", "", "", "" }; -/* Allow insmod to write those HP100_DEVICES strings individually */ -MODULE_PARM(hp100_name, "1-" __MODULE_STRING(HP100_DEVICES) "c" __MODULE_STRING(IFNAMSIZ)); - /* List of devices */ static struct net_device *hp100_devlist[HP100_DEVICES]; -static void release_dev(int i) +static int __init hp100_isa_init(void) { - struct net_device *d = hp100_devlist[i]; - struct hp100_private *p = (struct hp100_private *) d->priv; + struct net_device *dev; + int i, err, cards = 0; - unregister_netdev(d); - release_region(d->base_addr, HP100_REGION_SIZE); + /* Don't autoprobe ISA bus */ + if (hp100_port[0] == 0) + return -ENODEV; - if (p->mode == 1) /* busmaster */ - pci_free_consistent(p->pci_dev, MAX_RINGSIZE + 0x0f, p->page_vaddr_algn, virt_to_whatever(d, p->page_vaddr_algn)); - if (p->mem_ptr_virt) - iounmap(p->mem_ptr_virt); - kfree(d->priv); - d->priv = NULL; - free_netdev(d); - hp100_devlist[i] = NULL; + /* Loop on all possible base addresses */ + for (i = 0; i < HP100_DEVICES && hp100_port[i] != -1; ++i) { + dev = alloc_etherdev(sizeof(struct hp100_private)); + if (!dev) { + printk(KERN_WARNING "hp100: no memory for network device\n"); + while (cards > 0) + cleanup_dev(hp100_devlist[--cards]); + + return -ENOMEM; + } + SET_MODULE_OWNER(dev); + + err = hp100_isa_probe(dev, hp100_port[i]); + if (!err) { + err = register_netdev(dev); + if (!err) + hp100_devlist[cards++] = dev; + else + release_region(dev->base_addr, HP100_REGION_SIZE); + } + + if (err) + free_netdev(dev); + } + + return cards > 0 ? 0 : -ENODEV; } -static int __init hp100_module_init(void) +static void __exit hp100_isa_cleanup(void) { - int i, cards; + int i; -#ifndef CONFIG_PCI - if (hp100_port == 0 && !EISA_bus) - printk("hp100: You should not use auto-probing with insmod!\n"); + for (i = 0; i < HP100_DEVICES; i++) { + struct net_device *dev = hp100_devlist[i]; + if (dev) + cleanup_dev(dev); + } +} +#else +#define hp100_isa_init() (0) +#define hp100_isa_cleanup() do { } while(0) #endif - /* Loop on all possible base addresses */ - i = -1; - cards = 0; - while ((hp100_port[++i] != -1) && (i < HP100_DEVICES)) { - /* Create device and set basics args */ - hp100_devlist[i] = kmalloc(sizeof(struct net_device), GFP_KERNEL); - if (!hp100_devlist[i]) - goto fail; - memset(hp100_devlist[i], 0x00, sizeof(struct net_device)); -#if LINUX_VERSION_CODE >= 0x020362 /* 2.3.99-pre7 */ - memcpy(hp100_devlist[i]->name, hp100_name[i], IFNAMSIZ); /* Copy name */ -#else - hp100_devlist[i]->name = hp100_name[i]; -#endif /* LINUX_VERSION_CODE >= 0x020362 */ - hp100_devlist[i]->base_addr = hp100_port[i]; - hp100_devlist[i]->init = &hp100_probe; - - /* Try to create the device */ - if (register_netdev(hp100_devlist[i]) != 0) { - /* DeAllocate everything */ - /* Note: if dev->priv is mallocated, there is no way to fail */ - kfree(hp100_devlist[i]); - hp100_devlist[i] = (struct net_device *) NULL; - } else - cards++; - } /* Loop over all devices */ +static int __init hp100_module_init(void) +{ + int err; - return cards > 0 ? 0 : -ENODEV; - fail: - while (cards && --i) - if (hp100_devlist[i]) { - release_dev(i); - --cards; - } - return -ENOMEM; + err = hp100_isa_init(); + +#ifdef CONFIG_EISA + err |= eisa_driver_register(&hp100_eisa_driver); +#endif +#ifdef CONFIG_PCI + err |= pci_module_init(&hp100_pci_driver); +#endif + return err; } + static void __exit hp100_module_exit(void) { - int i; - - /* TODO: Check if all skb's are released/freed. */ - for (i = 0; i < HP100_DEVICES; i++) - if (hp100_devlist[i] != (struct net_device *) NULL) - release_dev(i); + hp100_isa_cleanup(); +#ifdef CONFIG_EISA + eisa_driver_unregister (&hp100_eisa_driver); +#endif +#ifdef CONFIG_PCI + pci_unregister_driver (&hp100_pci_driver); +#endif } module_init(hp100_module_init) module_exit(hp100_module_exit) -#endif /* MODULE */ - /* * Local variables: diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 3ebce2229e34..deae06d15974 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -631,6 +631,8 @@ #define PCI_DEVICE_ID_HP_TACHLITE 0x1029 #define PCI_DEVICE_ID_HP_J2585A 0x1030 #define PCI_DEVICE_ID_HP_J2585B 0x1031 +#define PCI_DEVICE_ID_HP_J2973A 0x1040 +#define PCI_DEVICE_ID_HP_J2970A 0x1042 #define PCI_DEVICE_ID_HP_DIVA 0x1048 #define PCI_DEVICE_ID_HP_DIVA_TOSCA1 0x1049 #define PCI_DEVICE_ID_HP_DIVA_TOSCA2 0x104A -- cgit v1.2.3 From c67928f817c26a33c24f90a11f1cc7743ea23ec2 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 24 Jan 2004 19:09:19 -0800 Subject: [SCTP]: Fix packed attribute usage. --- include/linux/sctp.h | 62 ++++++++++++++++++++++------------------------ include/net/sctp/structs.h | 2 +- 2 files changed, 31 insertions(+), 33 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sctp.h b/include/linux/sctp.h index 9ddc3bd5cd81..a851af99af70 100644 --- a/include/linux/sctp.h +++ b/include/linux/sctp.h @@ -61,14 +61,14 @@ typedef struct sctphdr { __u16 dest; __u32 vtag; __u32 checksum; -} sctp_sctphdr_t __attribute__((packed)); +} __attribute__((packed)) sctp_sctphdr_t; /* Section 3.2. Chunk Field Descriptions. */ typedef struct sctp_chunkhdr { __u8 type; __u8 flags; __u16 length; -} sctp_chunkhdr_t __attribute__((packed)); +} __attribute__((packed)) sctp_chunkhdr_t; /* Section 3.2. Chunk Type Values. @@ -152,7 +152,7 @@ enum { SCTP_CHUNK_FLAG_T = 0x01 }; typedef struct sctp_paramhdr { __u16 type; __u16 length; -} sctp_paramhdr_t __attribute((packed)); +} __attribute__((packed)) sctp_paramhdr_t; typedef enum { @@ -202,12 +202,12 @@ typedef struct sctp_datahdr { __u16 ssn; __u32 ppid; __u8 payload[0]; -} sctp_datahdr_t __attribute__((packed)); +} __attribute__((packed)) sctp_datahdr_t; typedef struct sctp_data_chunk { sctp_chunkhdr_t chunk_hdr; sctp_datahdr_t data_hdr; -} sctp_data_chunk_t __attribute__((packed)); +} __attribute__((packed)) sctp_data_chunk_t; /* DATA Chuck Specific Flags */ enum { @@ -232,48 +232,48 @@ typedef struct sctp_inithdr { __u16 num_inbound_streams; __u32 initial_tsn; __u8 params[0]; -} sctp_inithdr_t __attribute__((packed)); +} __attribute__((packed)) sctp_inithdr_t; typedef struct sctp_init_chunk { sctp_chunkhdr_t chunk_hdr; sctp_inithdr_t init_hdr; -} sctp_init_chunk_t __attribute__((packed)); +} __attribute__((packed)) sctp_init_chunk_t; /* Section 3.3.2.1. IPv4 Address Parameter (5) */ typedef struct sctp_ipv4addr_param { sctp_paramhdr_t param_hdr; struct in_addr addr; -} sctp_ipv4addr_param_t __attribute__((packed)); +} __attribute__((packed)) sctp_ipv4addr_param_t; /* Section 3.3.2.1. IPv6 Address Parameter (6) */ typedef struct sctp_ipv6addr_param { sctp_paramhdr_t param_hdr; struct in6_addr addr; -} sctp_ipv6addr_param_t __attribute__((packed)); +} __attribute__((packed)) sctp_ipv6addr_param_t; /* Section 3.3.2.1 Cookie Preservative (9) */ typedef struct sctp_cookie_preserve_param { sctp_paramhdr_t param_hdr; uint32_t lifespan_increment; -} sctp_cookie_preserve_param_t __attribute__((packed)); +} __attribute__((packed)) sctp_cookie_preserve_param_t; /* Section 3.3.2.1 Host Name Address (11) */ typedef struct sctp_hostname_param { sctp_paramhdr_t param_hdr; uint8_t hostname[0]; -} sctp_hostname_param_t __attribute__((packed)); +} __attribute__((packed)) sctp_hostname_param_t; /* Section 3.3.2.1 Supported Address Types (12) */ typedef struct sctp_supported_addrs_param { sctp_paramhdr_t param_hdr; uint16_t types[0]; -} sctp_supported_addrs_param_t __attribute__((packed)); +} __attribute__((packed)) sctp_supported_addrs_param_t; /* Appendix A. ECN Capable (32768) */ typedef struct sctp_ecn_capable_param { sctp_paramhdr_t param_hdr; -} sctp_ecn_capable_param_t __attribute__((packed)); +} __attribute__((packed)) sctp_ecn_capable_param_t; @@ -287,13 +287,13 @@ typedef sctp_init_chunk_t sctp_initack_chunk_t; typedef struct sctp_cookie_param { sctp_paramhdr_t p; __u8 body[0]; -} sctp_cookie_param_t __attribute__((packed)); +} __attribute__((packed)) sctp_cookie_param_t; /* Section 3.3.3.1 Unrecognized Parameters (8) */ typedef struct sctp_unrecognized_param { sctp_paramhdr_t param_hdr; sctp_paramhdr_t unrecognized; -} sctp_unrecognized_param_t __attribute__((packed)); +} __attribute__((packed)) sctp_unrecognized_param_t; @@ -308,7 +308,7 @@ typedef struct sctp_unrecognized_param { typedef struct sctp_gap_ack_block { __u16 start; __u16 end; -} sctp_gap_ack_block_t __attribute__((packed)); +} __attribute__((packed)) sctp_gap_ack_block_t; typedef uint32_t sctp_dup_tsn_t; @@ -323,12 +323,12 @@ typedef struct sctp_sackhdr { __u16 num_gap_ack_blocks; __u16 num_dup_tsns; sctp_sack_variable_t variable[0]; -} sctp_sackhdr_t __attribute__((packed)); +} __attribute__((packed)) sctp_sackhdr_t; typedef struct sctp_sack_chunk { sctp_chunkhdr_t chunk_hdr; sctp_sackhdr_t sack_hdr; -} sctp_sack_chunk_t __attribute__((packed)); +} __attribute__((packed)) sctp_sack_chunk_t; /* RFC 2960. Section 3.3.5 Heartbeat Request (HEARTBEAT) (4): @@ -340,12 +340,12 @@ typedef struct sctp_sack_chunk { typedef struct sctp_heartbeathdr { sctp_paramhdr_t info; -} sctp_heartbeathdr_t __attribute__((packed)); +} __attribute__((packed)) sctp_heartbeathdr_t; typedef struct sctp_heartbeat_chunk { sctp_chunkhdr_t chunk_hdr; sctp_heartbeathdr_t hb_hdr; -} sctp_heartbeat_chunk_t __attribute__((packed)); +} __attribute__((packed)) sctp_heartbeat_chunk_t; /* For the abort and shutdown ACK we must carry the init tag in the @@ -354,7 +354,7 @@ typedef struct sctp_heartbeat_chunk { */ typedef struct sctp_abort_chunk { sctp_chunkhdr_t uh; -} sctp_abort_chunkt_t __attribute__((packed)); +} __attribute__((packed)) sctp_abort_chunkt_t; /* For the graceful shutdown we must carry the tag (in common header) @@ -362,14 +362,12 @@ typedef struct sctp_abort_chunk { */ typedef struct sctp_shutdownhdr { __u32 cum_tsn_ack; -} sctp_shutdownhdr_t __attribute__((packed)); +} __attribute__((packed)) sctp_shutdownhdr_t; struct sctp_shutdown_chunk_t { sctp_chunkhdr_t chunk_hdr; sctp_shutdownhdr_t shutdown_hdr; -} __attribute__((packed)); - - +} __attribute__ ((packed)); /* RFC 2960. Section 3.3.10 Operation Error (ERROR) (9) */ @@ -377,12 +375,12 @@ typedef struct sctp_errhdr { __u16 cause; __u16 length; __u8 variable[0]; -} sctp_errhdr_t __attribute__((packed)); +} __attribute__((packed)) sctp_errhdr_t; typedef struct sctp_operr_chunk { sctp_chunkhdr_t chunk_hdr; sctp_errhdr_t err_hdr; -} sctp_operr_chunk_t __attribute__((packed)); +} __attribute__((packed)) sctp_operr_chunk_t; /* RFC 2960 3.3.10 - Operation Error * @@ -460,7 +458,7 @@ typedef struct sctp_ecnehdr { typedef struct sctp_ecne_chunk { sctp_chunkhdr_t chunk_hdr; sctp_ecnehdr_t ence_hdr; -} sctp_ecne_chunk_t __attribute__((packed)); +} __attribute__((packed)) sctp_ecne_chunk_t; /* RFC 2960. Appendix A. Explicit Congestion Notification. * Congestion Window Reduced (CWR) (13) @@ -472,7 +470,7 @@ typedef struct sctp_cwrhdr { typedef struct sctp_cwr_chunk { sctp_chunkhdr_t chunk_hdr; sctp_cwrhdr_t cwr_hdr; -} sctp_cwr_chunk_t __attribute__((packed)); +} __attribute__((packed)) sctp_cwr_chunk_t; /* * ADDIP Section 3.1 New Chunk Types @@ -513,16 +511,16 @@ typedef struct sctp_cwr_chunk { typedef struct sctp_addip_param { sctp_paramhdr_t param_hdr; __u32 crr_id; -}sctp_addip_param_t __attribute__((packed)); +} __attribute__((packed)) sctp_addip_param_t; typedef struct sctp_addiphdr { __u32 serial; __u8 params[0]; -} sctp_addiphdr_t __attribute__((packed)); +} __attribute__((packed)) sctp_addiphdr_t; typedef struct sctp_addip_chunk { sctp_chunkhdr_t chunk_hdr; sctp_addiphdr_t addip_hdr; -} sctp_addip_chunk_t __attribute__((packed)); +} __attribute__((packed)) sctp_addip_chunk_t; #endif /* __LINUX_SCTP_H__ */ diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 92394f3de76a..a36880e6733f 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -369,7 +369,7 @@ typedef struct sctp_sender_hb_info { struct sctp_paramhdr param_hdr; union sctp_addr daddr; unsigned long sent_at; -} sctp_sender_hb_info_t __attribute__((packed)); +} __attribute__((packed)) sctp_sender_hb_info_t; /* * RFC 2960 1.3.2 Sequenced Delivery within Streams -- cgit v1.2.3 From e06af8c40d819c5c6bb1dae632944be4f6a48ddc Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 25 Jan 2004 07:09:33 -0800 Subject: [SUNGEM]: Add K2_GMAC pci id to pci_ids.h --- include/linux/pci_ids.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 4dba6ec06e3a..becde5e0fd9d 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -807,6 +807,7 @@ #define PCI_DEVICE_ID_APPLE_UNI_N_AGP2 0x0034 #define PCI_DEVICE_ID_APPLE_KAUAI_ATA 0x003b #define PCI_DEVICE_ID_APPLE_KEYLARGO_I 0x003e +#define PCI_DEVICE_ID_APPLE_K2_GMAC 0x004c #define PCI_DEVICE_ID_APPLE_TIGON3 0x1645 #define PCI_VENDOR_ID_YAMAHA 0x1073 -- cgit v1.2.3 From 328ff99f1cffb1c7131b39306c136006cccec067 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 28 Jan 2004 00:01:28 -0800 Subject: [NETFILTER]: Fix locking in ip_conntrack. http://bugme.osdl.org/show_bug.cgi?id=1764 We're walking the expect list without the ip_conntrack_expect_tuple_lock. --- include/linux/netfilter_ipv4/ip_conntrack_core.h | 1 + net/ipv4/netfilter/ip_conntrack_standalone.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/netfilter_ipv4/ip_conntrack_core.h b/include/linux/netfilter_ipv4/ip_conntrack_core.h index ea15674261a2..4c8b5d189089 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack_core.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_core.h @@ -50,5 +50,6 @@ static inline int ip_conntrack_confirm(struct sk_buff *skb) extern struct list_head *ip_conntrack_hash; extern struct list_head ip_conntrack_expect_list; DECLARE_RWLOCK_EXTERN(ip_conntrack_lock); +DECLARE_RWLOCK_EXTERN(ip_conntrack_expect_tuple_lock); #endif /* _IP_CONNTRACK_CORE_H */ diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index 98811b60d5ab..53db0e454e4d 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -159,6 +159,7 @@ list_conntracks(char *buffer, char **start, off_t offset, int length) } /* Now iterate through expecteds. */ + READ_LOCK(&ip_conntrack_expect_tuple_lock); list_for_each(e, &ip_conntrack_expect_list) { unsigned int last_len; struct ip_conntrack_expect *expect @@ -169,10 +170,12 @@ list_conntracks(char *buffer, char **start, off_t offset, int length) len += print_expect(buffer + len, expect); if (len > length) { len = last_len; - goto finished; + goto finished_expects; } } + finished_expects: + READ_UNLOCK(&ip_conntrack_expect_tuple_lock); finished: READ_UNLOCK(&ip_conntrack_lock); -- cgit v1.2.3 From 6e22ce74ea0666a869ce82f418ce78b5be089fb4 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 28 Jan 2004 20:15:03 -0800 Subject: [NET_SCHED]: Add HFSC packet scheduler. --- include/linux/pkt_sched.h | 31 + include/net/pkt_sched.h | 3 + net/sched/Kconfig | 11 +- net/sched/sch_hfsc.c | 1864 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1908 insertions(+), 1 deletion(-) create mode 100644 net/sched/sch_hfsc.c (limited to 'include/linux') diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index d97edad0effc..8ae0e141cb05 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -290,6 +290,37 @@ struct tc_htb_xstats __u32 ctokens; }; +/* HFSC section */ + +struct tc_hfsc_qopt +{ + __u16 defcls; /* default class */ +}; + +struct tc_service_curve +{ + __u32 m1; /* slope of the first segment in bps */ + __u32 d; /* x-projection of the first segment in us */ + __u32 m2; /* slope of the second segment in bps */ +}; + +struct tc_hfsc_stats +{ + __u64 work; /* total work done */ + __u64 rtwork; /* work done by real-time criteria */ + __u32 period; /* current period */ + __u32 level; /* class level in hierarchy */ +}; + +enum +{ + TCA_HFSC_UNSPEC, + TCA_HFSC_RSC, + TCA_HFSC_FSC, + TCA_HFSC_USC, + TCA_HFSC_MAX = TCA_HFSC_USC +}; + /* CBQ section */ #define TC_CBQ_MAXPRIO 8 diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index 270523896c4d..35f600ba43ba 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -203,6 +203,7 @@ typedef long psched_tdiff_t; #define PSCHED_GET_TIME(stamp) do_gettimeofday(&(stamp)) #define PSCHED_US2JIFFIE(usecs) (((usecs)+(1000000/HZ-1))/(1000000/HZ)) +#define PSCHED_JIFFIE2US(delay) ((delay)*(1000000/HZ)) #define PSCHED_EXPORTLIST EXPORT_SYMBOL(psched_tod_diff); @@ -251,6 +252,7 @@ extern PSCHED_WATCHER psched_time_mark; #endif #define PSCHED_US2JIFFIE(delay) (((delay)+(1<>PSCHED_JSCALE) +#define PSCHED_JIFFIE2US(delay) ((delay)< + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 2003-10-17 - Ported from altq + */ +/* + * Copyright (c) 1997-1999 Carnegie Mellon University. All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation is hereby granted (including for commercial or + * for-profit use), provided that both the copyright notice and this + * permission notice appear in all copies of the software, derivative + * works, or modified versions, and any portions thereof. + * + * THIS SOFTWARE IS EXPERIMENTAL AND IS KNOWN TO HAVE BUGS, SOME OF + * WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON PROVIDES THIS + * SOFTWARE IN ITS ``AS IS'' CONDITION, AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * Carnegie Mellon encourages (but does not require) users of this + * software to return any improvements or extensions that they make, + * and to grant Carnegie Mellon the rights to redistribute these + * changes without encumbrance. + */ +/* + * H-FSC is described in Proceedings of SIGCOMM'97, + * "A Hierarchical Fair Service Curve Algorithm for Link-Sharing, + * Real-Time and Priority Service" + * by Ion Stoica, Hui Zhang, and T. S. Eugene Ng. + * + * Oleg Cherevko added the upperlimit for link-sharing. + * when a class has an upperlimit, the fit-time is computed from the + * upperlimit service curve. the link-sharing scheduler does not schedule + * a class whose fit-time exceeds the current time. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HFSC_DEBUG 1 + +/* + * kernel internal service curve representation: + * coordinates are given by 64 bit unsigned integers. + * x-axis: unit is clock count. + * y-axis: unit is byte. + * + * The service curve parameters are converted to the internal + * representation. The slope values are scaled to avoid overflow. + * the inverse slope values as well as the y-projection of the 1st + * segment are kept in order to to avoid 64-bit divide operations + * that are expensive on 32-bit architectures. + */ + +struct internal_sc +{ + u64 sm1; /* scaled slope of the 1st segment */ + u64 ism1; /* scaled inverse-slope of the 1st segment */ + u64 dx; /* the x-projection of the 1st segment */ + u64 dy; /* the y-projection of the 1st segment */ + u64 sm2; /* scaled slope of the 2nd segment */ + u64 ism2; /* scaled inverse-slope of the 2nd segment */ +}; + +/* runtime service curve */ +struct runtime_sc +{ + u64 x; /* current starting position on x-axis */ + u64 y; /* current starting position on y-axis */ + u64 sm1; /* scaled slope of the 1st segment */ + u64 ism1; /* scaled inverse-slope of the 1st segment */ + u64 dx; /* the x-projection of the 1st segment */ + u64 dy; /* the y-projection of the 1st segment */ + u64 sm2; /* scaled slope of the 2nd segment */ + u64 ism2; /* scaled inverse-slope of the 2nd segment */ +}; + +enum hfsc_class_flags +{ + HFSC_RSC = 0x1, + HFSC_FSC = 0x2, + HFSC_USC = 0x4 +}; + +struct hfsc_class +{ + u32 classid; /* class id */ + unsigned int refcnt; /* usage count */ + + struct tc_stats stats; /* generic statistics */ + unsigned int level; /* class level in hierarchy */ + struct tcf_proto *filter_list; /* filter list */ + unsigned int filter_cnt; /* filter count */ + + struct hfsc_sched *sched; /* scheduler data */ + struct hfsc_class *cl_parent; /* parent class */ + struct list_head siblings; /* sibling classes */ + struct list_head children; /* child classes */ + struct Qdisc *qdisc; /* leaf qdisc */ + + struct list_head actlist; /* active children list */ + struct list_head alist; /* active children list member */ + struct list_head ellist; /* eligible list member */ + struct list_head hlist; /* hash list member */ + struct list_head dlist; /* drop list member */ + + u64 cl_total; /* total work in bytes */ + u64 cl_cumul; /* cumulative work in bytes done by + real-time criteria */ + + u64 cl_d; /* deadline*/ + u64 cl_e; /* eligible time */ + u64 cl_vt; /* virtual time */ + u64 cl_f; /* time when this class will fit for + link-sharing, max(myf, cfmin) */ + u64 cl_myf; /* my fit-time (calculated from this + class's own upperlimit curve) */ + u64 cl_myfadj; /* my fit-time adjustment (to cancel + history dependence) */ + u64 cl_cfmin; /* earliest children's fit-time (used + with cl_myf to obtain cl_f) */ + u64 cl_cvtmin; /* minimal virtual time among the + children fit for link-sharing + (monotonic within a period) */ + u64 cl_vtadj; /* intra-period cumulative vt + adjustment */ + u64 cl_vtoff; /* inter-period cumulative vt offset */ + u64 cl_cvtmax; /* max child's vt in the last period */ + + struct internal_sc cl_rsc; /* internal real-time service curve */ + struct internal_sc cl_fsc; /* internal fair service curve */ + struct internal_sc cl_usc; /* internal upperlimit service curve */ + struct runtime_sc cl_deadline; /* deadline curve */ + struct runtime_sc cl_eligible; /* eligible curve */ + struct runtime_sc cl_virtual; /* virtual curve */ + struct runtime_sc cl_ulimit; /* upperlimit curve */ + + unsigned long cl_flags; /* which curves are valid */ + unsigned long cl_vtperiod; /* vt period sequence number */ + unsigned long cl_parentperiod;/* parent's vt period sequence number*/ + unsigned long cl_nactive; /* number of active children */ +}; + +#define HFSC_HSIZE 16 + +struct hfsc_sched +{ + u16 defcls; /* default class id */ + + struct hfsc_class root; /* root class */ + struct hfsc_class *last_xmit; /* class that transmitted last + packet (for requeueing) */ + struct list_head clhash[HFSC_HSIZE]; /* class hash */ + struct list_head eligible; /* eligible list */ + struct list_head droplist; /* active leaf class list (for + dropping) */ + struct timer_list wd_timer; /* watchdog timer */ +}; + +/* + * macros + */ +#if PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY +#include +#undef PSCHED_GET_TIME +#define PSCHED_GET_TIME(stamp) \ +do { \ + struct timeval tv; \ + do_gettimeofday(&tv); \ + (stamp) = 1000000ULL * tv.tv_sec + tv.tv_usec; \ +} while (0) +#endif + +#if HFSC_DEBUG +#define ASSERT(cond) \ +do { \ + if (unlikely(!(cond))) \ + printk("assertion %s failed at %s:%i (%s)\n", \ + #cond, __FILE__, __LINE__, __FUNCTION__); \ +} while (0) +#else +#define ASSERT(cond) +#endif /* HFSC_DEBUG */ + +#define HT_INFINITY 0xffffffffffffffffULL /* infinite time value */ + + +/* + * eligible list holds backlogged classes being sorted by their eligible times. + * there is one eligible list per hfsc instance. + */ + +static void +ellist_insert(struct hfsc_class *cl) +{ + struct list_head *head = &cl->sched->eligible; + struct hfsc_class *p; + + /* check the last entry first */ + if (list_empty(head) || + ((p = list_entry(head->prev, struct hfsc_class, ellist)) && + p->cl_e <= cl->cl_e)) { + list_add_tail(&cl->ellist, head); + return; + } + + list_for_each_entry(p, head, ellist) { + if (cl->cl_e < p->cl_e) { + /* insert cl before p */ + list_add_tail(&cl->ellist, &p->ellist); + return; + } + } + ASSERT(0); /* should not reach here */ +} + +static inline void +ellist_remove(struct hfsc_class *cl) +{ + list_del(&cl->ellist); +} + +static void +ellist_update(struct hfsc_class *cl) +{ + struct list_head *head = &cl->sched->eligible; + struct hfsc_class *p, *last; + + /* + * the eligible time of a class increases monotonically. + * if the next entry has a larger eligible time, nothing to do. + */ + if (cl->ellist.next == head || + ((p = list_entry(cl->ellist.next, struct hfsc_class, ellist)) && + cl->cl_e <= p->cl_e)) + return; + + /* check the last entry */ + last = list_entry(head->prev, struct hfsc_class, ellist); + if (last->cl_e <= cl->cl_e) { + list_move_tail(&cl->ellist, head); + return; + } + + /* + * the new position must be between the next entry + * and the last entry + */ + list_for_each_entry_continue(p, head, ellist) { + if (cl->cl_e < p->cl_e) { + list_move_tail(&cl->ellist, &p->ellist); + return; + } + } + ASSERT(0); /* should not reach here */ +} + +/* find the class with the minimum deadline among the eligible classes */ +static inline struct hfsc_class * +ellist_get_mindl(struct list_head *head, u64 cur_time) +{ + struct hfsc_class *p, *cl = NULL; + + list_for_each_entry(p, head, ellist) { + if (p->cl_e > cur_time) + break; + if (cl == NULL || p->cl_d < cl->cl_d) + cl = p; + } + return cl; +} + +/* find the class with minimum eligible time among the eligible classes */ +static inline struct hfsc_class * +ellist_get_minel(struct list_head *head) +{ + if (list_empty(head)) + return NULL; + return list_entry(head->next, struct hfsc_class, ellist); +} + +/* + * active children list holds backlogged child classes being sorted + * by their virtual time. each intermediate class has one active + * children list. + */ +static void +actlist_insert(struct hfsc_class *cl) +{ + struct list_head *head = &cl->cl_parent->actlist; + struct hfsc_class *p; + + /* check the last entry first */ + if (list_empty(head) || + ((p = list_entry(head->prev, struct hfsc_class, alist)) && + p->cl_vt <= cl->cl_vt)) { + list_add_tail(&cl->alist, head); + return; + } + + list_for_each_entry(p, head, alist) { + if (cl->cl_vt < p->cl_vt) { + /* insert cl before p */ + list_add_tail(&cl->alist, &p->alist); + return; + } + } + ASSERT(0); /* should not reach here */ +} + +static inline void +actlist_remove(struct hfsc_class *cl) +{ + list_del(&cl->alist); +} + +static void +actlist_update(struct hfsc_class *cl) +{ + struct list_head *head = &cl->cl_parent->actlist; + struct hfsc_class *p, *last; + + /* + * the virtual time of a class increases monotonically. + * if the next entry has a larger virtual time, nothing to do. + */ + if (cl->alist.next == head || + ((p = list_entry(cl->alist.next, struct hfsc_class, alist)) && + cl->cl_vt <= p->cl_vt)) + return; + + /* check the last entry */ + last = list_entry(head->prev, struct hfsc_class, alist); + if (last->cl_vt <= cl->cl_vt) { + list_move_tail(&cl->alist, head); + return; + } + + /* + * the new position must be between the next entry + * and the last entry + */ + list_for_each_entry_continue(p, head, alist) { + if (cl->cl_vt < p->cl_vt) { + list_move_tail(&cl->alist, &p->alist); + return; + } + } + ASSERT(0); /* should not reach here */ +} + +static inline struct hfsc_class * +actlist_firstfit(struct hfsc_class *cl, u64 cur_time) +{ + struct hfsc_class *p; + + list_for_each_entry(p, &cl->actlist, alist) { + if (p->cl_f <= cur_time) { + return p; + } + } + return NULL; +} + +/* + * get the leaf class with the minimum vt in the hierarchy + */ +static struct hfsc_class * +actlist_get_minvt(struct hfsc_class *cl, u64 cur_time) +{ + /* if root-class's cfmin is bigger than cur_time nothing to do */ + if (cl->cl_cfmin > cur_time) + return NULL; + + while (cl->level > 0) { + cl = actlist_firstfit(cl, cur_time); + if (cl == NULL) + return NULL; + /* + * update parent's cl_cvtmin. + */ + if (cl->cl_parent->cl_cvtmin < cl->cl_vt) + cl->cl_parent->cl_cvtmin = cl->cl_vt; + } + return cl; +} + +/* + * service curve support functions + * + * external service curve parameters + * m: bps + * d: us + * internal service curve parameters + * sm: (bytes/psched_us) << SM_SHIFT + * ism: (psched_us/byte) << ISM_SHIFT + * dx: psched_us + * + * Time source resolution + * PSCHED_JIFFIES: for 48<=HZ<=1534 resolution is between 0.63us and 1.27us. + * PSCHED_CPU: resolution is between 0.5us and 1us. + * PSCHED_GETTIMEOFDAY: resolution is exactly 1us. + * + * sm and ism are scaled in order to keep effective digits. + * SM_SHIFT and ISM_SHIFT are selected to keep at least 4 effective + * digits in decimal using the following table. + * + * Note: We can afford the additional accuracy (altq hfsc keeps at most + * 3 effective digits) thanks to the fact that linux clock is bounded + * much more tightly. + * + * bits/sec 100Kbps 1Mbps 10Mbps 100Mbps 1Gbps + * ------------+------------------------------------------------------- + * bytes/0.5us 6.25e-3 62.5e-3 625e-3 6250e-e 62500e-3 + * bytes/us 12.5e-3 125e-3 1250e-3 12500e-3 125000e-3 + * bytes/1.27us 15.875e-3 158.75e-3 1587.5e-3 15875e-3 158750e-3 + * + * 0.5us/byte 160 16 1.6 0.16 0.016 + * us/byte 80 8 0.8 0.08 0.008 + * 1.27us/byte 63 6.3 0.63 0.063 0.0063 + */ +#define SM_SHIFT 20 +#define ISM_SHIFT 18 + +#define SM_MASK ((1ULL << SM_SHIFT) - 1) +#define ISM_MASK ((1ULL << ISM_SHIFT) - 1) + +static inline u64 +seg_x2y(u64 x, u64 sm) +{ + u64 y; + + /* + * compute + * y = x * sm >> SM_SHIFT + * but divide it for the upper and lower bits to avoid overflow + */ + y = (x >> SM_SHIFT) * sm + (((x & SM_MASK) * sm) >> SM_SHIFT); + return y; +} + +static inline u64 +seg_y2x(u64 y, u64 ism) +{ + u64 x; + + if (y == 0) + x = 0; + else if (ism == HT_INFINITY) + x = HT_INFINITY; + else { + x = (y >> ISM_SHIFT) * ism + + (((y & ISM_MASK) * ism) >> ISM_SHIFT); + } + return x; +} + +/* Convert m (bps) into sm (bytes/psched us) */ +static u64 +m2sm(u32 m) +{ + u64 sm; + + sm = ((u64)m << SM_SHIFT); + sm += PSCHED_JIFFIE2US(HZ) - 1; + do_div(sm, PSCHED_JIFFIE2US(HZ)); + return sm; +} + +/* convert m (bps) into ism (psched us/byte) */ +static u64 +m2ism(u32 m) +{ + u64 ism; + + if (m == 0) + ism = HT_INFINITY; + else { + ism = ((u64)PSCHED_JIFFIE2US(HZ) << ISM_SHIFT); + ism += m - 1; + do_div(ism, m); + } + return ism; +} + +/* convert d (us) into dx (psched us) */ +static u64 +d2dx(u32 d) +{ + u64 dx; + + dx = ((u64)d * PSCHED_JIFFIE2US(HZ)); + dx += 1000000 - 1; + do_div(dx, 1000000); + return dx; +} + +/* convert sm (bytes/psched us) into m (bps) */ +static u32 +sm2m(u64 sm) +{ + u64 m; + + m = (sm * PSCHED_JIFFIE2US(HZ)) >> SM_SHIFT; + return (u32)m; +} + +/* convert dx (psched us) into d (us) */ +static u32 +dx2d(u64 dx) +{ + u64 d; + + d = dx * 1000000; + do_div(d, PSCHED_JIFFIE2US(HZ)); + return (u32)d; +} + +static void +sc2isc(struct tc_service_curve *sc, struct internal_sc *isc) +{ + isc->sm1 = m2sm(sc->m1); + isc->ism1 = m2ism(sc->m1); + isc->dx = d2dx(sc->d); + isc->dy = seg_x2y(isc->dx, isc->sm1); + isc->sm2 = m2sm(sc->m2); + isc->ism2 = m2ism(sc->m2); +} + +/* + * initialize the runtime service curve with the given internal + * service curve starting at (x, y). + */ +static void +rtsc_init(struct runtime_sc *rtsc, struct internal_sc *isc, u64 x, + u64 y) +{ + rtsc->x = x; + rtsc->y = y; + rtsc->sm1 = isc->sm1; + rtsc->ism1 = isc->ism1; + rtsc->dx = isc->dx; + rtsc->dy = isc->dy; + rtsc->sm2 = isc->sm2; + rtsc->ism2 = isc->ism2; +} + +/* + * calculate the y-projection of the runtime service curve by the + * given x-projection value + */ +static u64 +rtsc_y2x(struct runtime_sc *rtsc, u64 y) +{ + u64 x; + + if (y < rtsc->y) + x = rtsc->x; + else if (y <= rtsc->y + rtsc->dy) { + /* x belongs to the 1st segment */ + if (rtsc->dy == 0) + x = rtsc->x + rtsc->dx; + else + x = rtsc->x + seg_y2x(y - rtsc->y, rtsc->ism1); + } else { + /* x belongs to the 2nd segment */ + x = rtsc->x + rtsc->dx + + seg_y2x(y - rtsc->y - rtsc->dy, rtsc->ism2); + } + return x; +} + +static u64 +rtsc_x2y(struct runtime_sc *rtsc, u64 x) +{ + u64 y; + + if (x <= rtsc->x) + y = rtsc->y; + else if (x <= rtsc->x + rtsc->dx) + /* y belongs to the 1st segment */ + y = rtsc->y + seg_x2y(x - rtsc->x, rtsc->sm1); + else + /* y belongs to the 2nd segment */ + y = rtsc->y + rtsc->dy + + seg_x2y(x - rtsc->x - rtsc->dx, rtsc->sm2); + return y; +} + +/* + * update the runtime service curve by taking the minimum of the current + * runtime service curve and the service curve starting at (x, y). + */ +static void +rtsc_min(struct runtime_sc *rtsc, struct internal_sc *isc, u64 x, + u64 y) +{ + u64 y1, y2, dx, dy; + u32 dsm; + + if (isc->sm1 <= isc->sm2) { + /* service curve is convex */ + y1 = rtsc_x2y(rtsc, x); + if (y1 < y) + /* the current rtsc is smaller */ + return; + rtsc->x = x; + rtsc->y = y; + return; + } + + /* + * service curve is concave + * compute the two y values of the current rtsc + * y1: at x + * y2: at (x + dx) + */ + y1 = rtsc_x2y(rtsc, x); + if (y1 <= y) { + /* rtsc is below isc, no change to rtsc */ + return; + } + + y2 = rtsc_x2y(rtsc, x + isc->dx); + if (y2 >= y + isc->dy) { + /* rtsc is above isc, replace rtsc by isc */ + rtsc->x = x; + rtsc->y = y; + rtsc->dx = isc->dx; + rtsc->dy = isc->dy; + return; + } + + /* + * the two curves intersect + * compute the offsets (dx, dy) using the reverse + * function of seg_x2y() + * seg_x2y(dx, sm1) == seg_x2y(dx, sm2) + (y1 - y) + */ + dx = (y1 - y) << SM_SHIFT; + dsm = isc->sm1 - isc->sm2; + do_div(dx, dsm); + /* + * check if (x, y1) belongs to the 1st segment of rtsc. + * if so, add the offset. + */ + if (rtsc->x + rtsc->dx > x) + dx += rtsc->x + rtsc->dx - x; + dy = seg_x2y(dx, isc->sm1); + + rtsc->x = x; + rtsc->y = y; + rtsc->dx = dx; + rtsc->dy = dy; + return; +} + +static void +init_ed(struct hfsc_class *cl, unsigned int next_len) +{ + u64 cur_time; + + PSCHED_GET_TIME(cur_time); + + /* update the deadline curve */ + rtsc_min(&cl->cl_deadline, &cl->cl_rsc, cur_time, cl->cl_cumul); + + /* + * update the eligible curve. + * for concave, it is equal to the deadline curve. + * for convex, it is a linear curve with slope m2. + */ + cl->cl_eligible = cl->cl_deadline; + if (cl->cl_rsc.sm1 <= cl->cl_rsc.sm2) { + cl->cl_eligible.dx = 0; + cl->cl_eligible.dy = 0; + } + + /* compute e and d */ + cl->cl_e = rtsc_y2x(&cl->cl_eligible, cl->cl_cumul); + cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len); + + ellist_insert(cl); +} + +static void +update_ed(struct hfsc_class *cl, unsigned int next_len) +{ + cl->cl_e = rtsc_y2x(&cl->cl_eligible, cl->cl_cumul); + cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len); + + ellist_update(cl); +} + +static inline void +update_d(struct hfsc_class *cl, unsigned int next_len) +{ + cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len); +} + +static void +update_cfmin(struct hfsc_class *cl) +{ + struct hfsc_class *p; + u64 cfmin; + + if (list_empty(&cl->actlist)) { + cl->cl_cfmin = 0; + return; + } + cfmin = HT_INFINITY; + list_for_each_entry(p, &cl->actlist, alist) { + if (p->cl_f == 0) { + cl->cl_cfmin = 0; + return; + } + if (p->cl_f < cfmin) + cfmin = p->cl_f; + } + cl->cl_cfmin = cfmin; +} + +static void +init_vf(struct hfsc_class *cl, unsigned int len) +{ + struct hfsc_class *max_cl, *p; + u64 vt, f, cur_time; + int go_active; + + cur_time = 0; + go_active = 1; + for (; cl->cl_parent != NULL; cl = cl->cl_parent) { + if (go_active && cl->cl_nactive++ == 0) + go_active = 1; + else + go_active = 0; + + if (go_active) { + if (!list_empty(&cl->cl_parent->actlist)) { + max_cl = list_entry(cl->cl_parent->actlist.prev, + struct hfsc_class, alist); + /* + * set vt to the average of the min and max + * classes. if the parent's period didn't + * change, don't decrease vt of the class. + */ + vt = max_cl->cl_vt; + if (cl->cl_parent->cl_cvtmin != 0) + vt = (cl->cl_parent->cl_cvtmin + vt)/2; + + if (cl->cl_parent->cl_vtperiod != + cl->cl_parentperiod || vt > cl->cl_vt) + cl->cl_vt = vt; + } else { + /* + * first child for a new parent backlog period. + * add parent's cvtmax to vtoff of children + * to make a new vt (vtoff + vt) larger than + * the vt in the last period for all children. + */ + vt = cl->cl_parent->cl_cvtmax; + list_for_each_entry(p, &cl->cl_parent->children, + siblings) + p->cl_vtoff += vt; + cl->cl_vt = 0; + cl->cl_parent->cl_cvtmax = 0; + cl->cl_parent->cl_cvtmin = 0; + } + + /* update the virtual curve */ + vt = cl->cl_vt + cl->cl_vtoff; + rtsc_min(&cl->cl_virtual, &cl->cl_fsc, vt, + cl->cl_total); + if (cl->cl_virtual.x == vt) { + cl->cl_virtual.x -= cl->cl_vtoff; + cl->cl_vtoff = 0; + } + cl->cl_vtadj = 0; + + cl->cl_vtperiod++; /* increment vt period */ + cl->cl_parentperiod = cl->cl_parent->cl_vtperiod; + if (cl->cl_parent->cl_nactive == 0) + cl->cl_parentperiod++; + cl->cl_f = 0; + + actlist_insert(cl); + + if (cl->cl_flags & HFSC_USC) { + /* class has upper limit curve */ + if (cur_time == 0) + PSCHED_GET_TIME(cur_time); + + /* update the ulimit curve */ + rtsc_min(&cl->cl_ulimit, &cl->cl_usc, cur_time, + cl->cl_total); + /* compute myf */ + cl->cl_myf = rtsc_y2x(&cl->cl_ulimit, + cl->cl_total); + cl->cl_myfadj = 0; + } + } + + f = max(cl->cl_myf, cl->cl_cfmin); + if (f != cl->cl_f) { + cl->cl_f = f; + update_cfmin(cl->cl_parent); + } + } +} + +static void +update_vf(struct hfsc_class *cl, unsigned int len, u64 cur_time) +{ + u64 f; /* , myf_bound, delta; */ + int go_passive = 0; + + if (cl->qdisc->q.qlen == 0 && cl->cl_flags & HFSC_FSC) + go_passive = 1; + + for (; cl->cl_parent != NULL; cl = cl->cl_parent) { + cl->cl_total += len; + + if (!(cl->cl_flags & HFSC_FSC) || cl->cl_nactive == 0) + continue; + + if (go_passive && --cl->cl_nactive == 0) + go_passive = 1; + else + go_passive = 0; + + if (go_passive) { + /* no more active child, going passive */ + + /* update cvtmax of the parent class */ + if (cl->cl_vt > cl->cl_parent->cl_cvtmax) + cl->cl_parent->cl_cvtmax = cl->cl_vt; + + /* remove this class from the vt list */ + actlist_remove(cl); + + update_cfmin(cl->cl_parent); + + continue; + } + + /* + * update vt and f + */ + cl->cl_vt = rtsc_y2x(&cl->cl_virtual, cl->cl_total) + - cl->cl_vtoff + cl->cl_vtadj; + + /* + * if vt of the class is smaller than cvtmin, + * the class was skipped in the past due to non-fit. + * if so, we need to adjust vtadj. + */ + if (cl->cl_vt < cl->cl_parent->cl_cvtmin) { + cl->cl_vtadj += cl->cl_parent->cl_cvtmin - cl->cl_vt; + cl->cl_vt = cl->cl_parent->cl_cvtmin; + } + + /* update the vt list */ + actlist_update(cl); + + if (cl->cl_flags & HFSC_USC) { + cl->cl_myf = cl->cl_myfadj + rtsc_y2x(&cl->cl_ulimit, + cl->cl_total); +#if 0 + /* + * This code causes classes to stay way under their + * limit when multiple classes are used at gigabit + * speed. needs investigation. -kaber + */ + /* + * if myf lags behind by more than one clock tick + * from the current time, adjust myfadj to prevent + * a rate-limited class from going greedy. + * in a steady state under rate-limiting, myf + * fluctuates within one clock tick. + */ + myf_bound = cur_time - PSCHED_JIFFIE2US(1); + if (cl->cl_myf < myf_bound) { + delta = cur_time - cl->cl_myf; + cl->cl_myfadj += delta; + cl->cl_myf += delta; + } +#endif + } + + f = max(cl->cl_myf, cl->cl_cfmin); + if (f != cl->cl_f) { + cl->cl_f = f; + update_cfmin(cl->cl_parent); + } + } +} + +static void +set_active(struct hfsc_class *cl, unsigned int len) +{ + if (cl->cl_flags & HFSC_RSC) + init_ed(cl, len); + if (cl->cl_flags & HFSC_FSC) + init_vf(cl, len); + + list_add_tail(&cl->dlist, &cl->sched->droplist); +} + +static void +set_passive(struct hfsc_class *cl) +{ + if (cl->cl_flags & HFSC_RSC) + ellist_remove(cl); + + list_del(&cl->dlist); + + /* + * actlist is now handled in update_vf() so that update_vf(cl, 0, 0) + * needs to be called explicitly to remove a class from actlist + */ +} + +/* + * hack to get length of first packet in queue. + */ +static unsigned int +qdisc_peek_len(struct Qdisc *sch) +{ + struct sk_buff *skb; + unsigned int len; + + skb = sch->dequeue(sch); + if (skb == NULL) { + if (net_ratelimit()) + printk("qdisc_peek_len: non work-conserving qdisc ?\n"); + return 0; + } + len = skb->len; + if (unlikely(sch->ops->requeue(skb, sch) != NET_XMIT_SUCCESS)) { + if (net_ratelimit()) + printk("qdisc_peek_len: failed to requeue\n"); + return 0; + } + return len; +} + +static void +hfsc_purge_queue(struct Qdisc *sch, struct hfsc_class *cl) +{ + unsigned int len = cl->qdisc->q.qlen; + + qdisc_reset(cl->qdisc); + if (len > 0) { + update_vf(cl, 0, 0); + set_passive(cl); + sch->q.qlen -= len; + } +} + +static void +hfsc_adjust_levels(struct hfsc_class *cl) +{ + struct hfsc_class *p; + unsigned int level; + + do { + level = 0; + list_for_each_entry(p, &cl->children, siblings) { + if (p->level > level) + level = p->level; + } + cl->level = level + 1; + } while ((cl = cl->cl_parent) != NULL); +} + +static inline unsigned int +hfsc_hash(u32 h) +{ + h ^= h >> 8; + h ^= h >> 4; + + return h & (HFSC_HSIZE - 1); +} + +static inline struct hfsc_class * +hfsc_find_class(u32 classid, struct Qdisc *sch) +{ + struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_class *cl; + + list_for_each_entry(cl, &q->clhash[hfsc_hash(classid)], hlist) { + if (cl->classid == classid) + return cl; + } + return NULL; +} + +static void +hfsc_change_rsc(struct hfsc_class *cl, struct tc_service_curve *rsc, + u64 cur_time) +{ + sc2isc(rsc, &cl->cl_rsc); + rtsc_init(&cl->cl_deadline, &cl->cl_rsc, cur_time, cl->cl_cumul); + cl->cl_eligible = cl->cl_deadline; + if (cl->cl_rsc.sm1 <= cl->cl_rsc.sm2) { + cl->cl_eligible.dx = 0; + cl->cl_eligible.dy = 0; + } + cl->cl_flags |= HFSC_RSC; +} + +static void +hfsc_change_fsc(struct hfsc_class *cl, struct tc_service_curve *fsc) +{ + sc2isc(fsc, &cl->cl_fsc); + rtsc_init(&cl->cl_virtual, &cl->cl_fsc, cl->cl_vt, cl->cl_total); + cl->cl_flags |= HFSC_FSC; +} + +static void +hfsc_change_usc(struct hfsc_class *cl, struct tc_service_curve *usc, + u64 cur_time) +{ + sc2isc(usc, &cl->cl_usc); + rtsc_init(&cl->cl_ulimit, &cl->cl_usc, cur_time, cl->cl_total); + cl->cl_flags |= HFSC_USC; +} + +static int +hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, + struct rtattr **tca, unsigned long *arg) +{ + struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_class *cl = (struct hfsc_class *)*arg; + struct hfsc_class *parent = NULL; + struct rtattr *opt = tca[TCA_OPTIONS-1]; + struct rtattr *tb[TCA_HFSC_MAX]; + struct tc_service_curve *rsc = NULL, *fsc = NULL, *usc = NULL; + u64 cur_time; + + if (opt == NULL || + rtattr_parse(tb, TCA_HFSC_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt))) + return -EINVAL; + + if (tb[TCA_HFSC_RSC-1]) { + if (RTA_PAYLOAD(tb[TCA_HFSC_RSC-1]) < sizeof(*rsc)) + return -EINVAL; + rsc = RTA_DATA(tb[TCA_HFSC_RSC-1]); + if (rsc->m1 == 0 && rsc->m2 == 0) + rsc = NULL; + } + + if (tb[TCA_HFSC_FSC-1]) { + if (RTA_PAYLOAD(tb[TCA_HFSC_FSC-1]) < sizeof(*fsc)) + return -EINVAL; + fsc = RTA_DATA(tb[TCA_HFSC_FSC-1]); + if (fsc->m1 == 0 && fsc->m2 == 0) + fsc = NULL; + } + + if (tb[TCA_HFSC_USC-1]) { + if (RTA_PAYLOAD(tb[TCA_HFSC_USC-1]) < sizeof(*usc)) + return -EINVAL; + usc = RTA_DATA(tb[TCA_HFSC_USC-1]); + if (usc->m1 == 0 && usc->m2 == 0) + usc = NULL; + } + + if (cl != NULL) { + if (parentid) { + if (cl->cl_parent && cl->cl_parent->classid != parentid) + return -EINVAL; + if (cl->cl_parent == NULL && parentid != TC_H_ROOT) + return -EINVAL; + } + PSCHED_GET_TIME(cur_time); + + sch_tree_lock(sch); + if (rsc != NULL) + hfsc_change_rsc(cl, rsc, cur_time); + if (fsc != NULL) + hfsc_change_fsc(cl, fsc); + if (usc != NULL) + hfsc_change_usc(cl, usc, cur_time); + + if (cl->qdisc->q.qlen != 0) { + if (cl->cl_flags & HFSC_RSC) + update_ed(cl, qdisc_peek_len(cl->qdisc)); + if (cl->cl_flags & HFSC_FSC) + update_vf(cl, 0, cur_time); + } + sch_tree_unlock(sch); + +#ifdef CONFIG_NET_ESTIMATOR + if (tca[TCA_RATE-1]) { + qdisc_kill_estimator(&cl->stats); + qdisc_new_estimator(&cl->stats, tca[TCA_RATE-1]); + } +#endif + return 0; + } + + if (parentid == TC_H_ROOT) + return -EEXIST; + + parent = &q->root; + if (parentid) { + parent = hfsc_find_class(parentid, sch); + if (parent == NULL) + return -ENOENT; + } + + if (classid == 0 || TC_H_MAJ(classid ^ sch->handle) != 0) + return -EINVAL; + if (hfsc_find_class(classid, sch)) + return -EEXIST; + + if (rsc == NULL && fsc == NULL) + return -EINVAL; + + cl = kmalloc(sizeof(struct hfsc_class), GFP_KERNEL); + if (cl == NULL) + return -ENOBUFS; + memset(cl, 0, sizeof(struct hfsc_class)); + + if (rsc != NULL) + hfsc_change_rsc(cl, rsc, 0); + if (fsc != NULL) + hfsc_change_fsc(cl, fsc); + if (usc != NULL) + hfsc_change_usc(cl, usc, 0); + + cl->refcnt = 1; + cl->classid = classid; + cl->sched = q; + cl->cl_parent = parent; + cl->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); + if (cl->qdisc == NULL) + cl->qdisc = &noop_qdisc; + cl->stats.lock = &sch->dev->queue_lock; + INIT_LIST_HEAD(&cl->children); + INIT_LIST_HEAD(&cl->actlist); + + sch_tree_lock(sch); + list_add_tail(&cl->hlist, &q->clhash[hfsc_hash(classid)]); + list_add_tail(&cl->siblings, &parent->children); + if (parent->level == 0) + hfsc_purge_queue(sch, parent); + hfsc_adjust_levels(parent); + sch_tree_unlock(sch); + +#ifdef CONFIG_NET_ESTIMATOR + if (tca[TCA_RATE-1]) + qdisc_new_estimator(&cl->stats, tca[TCA_RATE-1]); +#endif + *arg = (unsigned long)cl; + return 0; +} + +static void +hfsc_destroy_filters(struct tcf_proto **fl) +{ + struct tcf_proto *tp; + + while ((tp = *fl) != NULL) { + *fl = tp->next; + tcf_destroy(tp); + } +} + +static void +hfsc_destroy_class(struct Qdisc *sch, struct hfsc_class *cl) +{ + struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + + hfsc_destroy_filters(&cl->filter_list); + qdisc_destroy(cl->qdisc); +#ifdef CONFIG_NET_ESTIMATOR + qdisc_kill_estimator(&cl->stats); +#endif + if (cl != &q->root) + kfree(cl); +} + +static int +hfsc_delete_class(struct Qdisc *sch, unsigned long arg) +{ + struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_class *cl = (struct hfsc_class *)arg; + + if (cl->level > 0 || cl->filter_cnt > 0 || cl == &q->root) + return -EBUSY; + + sch_tree_lock(sch); + + list_del(&cl->hlist); + list_del(&cl->siblings); + hfsc_adjust_levels(cl->cl_parent); + hfsc_purge_queue(sch, cl); + if (q->last_xmit == cl) + q->last_xmit = NULL; + + if (--cl->refcnt == 0) + hfsc_destroy_class(sch, cl); + + sch_tree_unlock(sch); + return 0; +} + +static struct hfsc_class * +hfsc_classify(struct sk_buff *skb, struct Qdisc *sch) +{ + struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_class *cl; + struct tcf_result res; + struct tcf_proto *tcf; + int result; + + if (TC_H_MAJ(skb->priority ^ sch->handle) == 0 && + (cl = hfsc_find_class(skb->priority, sch)) != NULL) + if (cl->level == 0) + return cl; + + tcf = q->root.filter_list; + while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) { +#ifdef CONFIG_NET_CLS_POLICE + if (result == TC_POLICE_SHOT) + return NULL; +#endif + if ((cl = (struct hfsc_class *)res.class) == NULL) { + if ((cl = hfsc_find_class(res.classid, sch)) == NULL) + break; /* filter selected invalid classid */ + } + + if (cl->level == 0) + return cl; /* hit leaf class */ + + /* apply inner filter chain */ + tcf = cl->filter_list; + } + + /* classification failed, try default class */ + cl = hfsc_find_class(TC_H_MAKE(TC_H_MAJ(sch->handle), q->defcls), sch); + if (cl == NULL || cl->level > 0) + return NULL; + + return cl; +} + +static int +hfsc_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, + struct Qdisc **old) +{ + struct hfsc_class *cl = (struct hfsc_class *)arg; + + if (cl == NULL) + return -ENOENT; + if (cl->level > 0) + return -EINVAL; + if (new == NULL) { + new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); + if (new == NULL) + new = &noop_qdisc; + } + + sch_tree_lock(sch); + hfsc_purge_queue(sch, cl); + *old = xchg(&cl->qdisc, new); + sch_tree_unlock(sch); + return 0; +} + +static struct Qdisc * +hfsc_class_leaf(struct Qdisc *sch, unsigned long arg) +{ + struct hfsc_class *cl = (struct hfsc_class *)arg; + + if (cl != NULL && cl->level == 0) + return cl->qdisc; + + return NULL; +} + +static unsigned long +hfsc_get_class(struct Qdisc *sch, u32 classid) +{ + struct hfsc_class *cl = hfsc_find_class(classid, sch); + + if (cl != NULL) + cl->refcnt++; + + return (unsigned long)cl; +} + +static void +hfsc_put_class(struct Qdisc *sch, unsigned long arg) +{ + struct hfsc_class *cl = (struct hfsc_class *)arg; + + if (--cl->refcnt == 0) + hfsc_destroy_class(sch, cl); +} + +static unsigned long +hfsc_bind_tcf(struct Qdisc *sch, unsigned long parent, u32 classid) +{ + struct hfsc_class *p = (struct hfsc_class *)parent; + struct hfsc_class *cl = hfsc_find_class(classid, sch); + + if (cl != NULL) { + if (p != NULL && p->level <= cl->level) + return 0; + cl->filter_cnt++; + } + + return (unsigned long)cl; +} + +static void +hfsc_unbind_tcf(struct Qdisc *sch, unsigned long arg) +{ + struct hfsc_class *cl = (struct hfsc_class *)arg; + + cl->filter_cnt--; +} + +static struct tcf_proto ** +hfsc_tcf_chain(struct Qdisc *sch, unsigned long arg) +{ + struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_class *cl = (struct hfsc_class *)arg; + + if (cl == NULL) + cl = &q->root; + + return &cl->filter_list; +} + +static int +hfsc_dump_sc(struct sk_buff *skb, int attr, struct internal_sc *sc) +{ + struct tc_service_curve tsc; + + tsc.m1 = sm2m(sc->sm1); + tsc.d = dx2d(sc->dx); + tsc.m2 = sm2m(sc->sm2); + RTA_PUT(skb, attr, sizeof(tsc), &tsc); + + return skb->len; + + rtattr_failure: + return -1; +} + +static inline int +hfsc_dump_curves(struct sk_buff *skb, struct hfsc_class *cl) +{ + if ((cl->cl_flags & HFSC_RSC) && + (hfsc_dump_sc(skb, TCA_HFSC_RSC, &cl->cl_rsc) < 0)) + goto rtattr_failure; + + if ((cl->cl_flags & HFSC_FSC) && + (hfsc_dump_sc(skb, TCA_HFSC_FSC, &cl->cl_fsc) < 0)) + goto rtattr_failure; + + if ((cl->cl_flags & HFSC_USC) && + (hfsc_dump_sc(skb, TCA_HFSC_USC, &cl->cl_usc) < 0)) + goto rtattr_failure; + + return skb->len; + + rtattr_failure: + return -1; +} + +static inline int +hfsc_dump_stats(struct sk_buff *skb, struct hfsc_class *cl) +{ + cl->stats.qlen = cl->qdisc->q.qlen; + if (qdisc_copy_stats(skb, &cl->stats) < 0) + goto rtattr_failure; + + return skb->len; + + rtattr_failure: + return -1; +} + +static inline int +hfsc_dump_xstats(struct sk_buff *skb, struct hfsc_class *cl) +{ + struct tc_hfsc_stats xstats; + + xstats.level = cl->level; + xstats.period = cl->cl_vtperiod; + xstats.work = cl->cl_total; + xstats.rtwork = cl->cl_cumul; + RTA_PUT(skb, TCA_XSTATS, sizeof(xstats), &xstats); + + return skb->len; + + rtattr_failure: + return -1; +} + +static int +hfsc_dump_class(struct Qdisc *sch, unsigned long arg, struct sk_buff *skb, + struct tcmsg *tcm) +{ + struct hfsc_class *cl = (struct hfsc_class *)arg; + unsigned char *b = skb->tail; + struct rtattr *rta = (struct rtattr *)b; + + tcm->tcm_parent = cl->cl_parent ? cl->cl_parent->classid : TC_H_ROOT; + tcm->tcm_handle = cl->classid; + if (cl->level == 0) + tcm->tcm_info = cl->qdisc->handle; + + RTA_PUT(skb, TCA_OPTIONS, 0, NULL); + if (hfsc_dump_curves(skb, cl) < 0) + goto rtattr_failure; + rta->rta_len = skb->tail - b; + + if ((hfsc_dump_stats(skb, cl) < 0) || + (hfsc_dump_xstats(skb, cl) < 0)) + goto rtattr_failure; + + return skb->len; + + rtattr_failure: + skb_trim(skb, b - skb->data); + return -1; +} + +static void +hfsc_walk(struct Qdisc *sch, struct qdisc_walker *arg) +{ + struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_class *cl; + unsigned int i; + + if (arg->stop) + return; + + for (i = 0; i < HFSC_HSIZE; i++) { + list_for_each_entry(cl, &q->clhash[i], hlist) { + if (arg->count < arg->skip) { + arg->count++; + continue; + } + if (arg->fn(sch, (unsigned long)cl, arg) < 0) { + arg->stop = 1; + return; + } + arg->count++; + } + } +} + +static void +hfsc_watchdog(unsigned long arg) +{ + struct Qdisc *sch = (struct Qdisc *)arg; + + sch->flags &= ~TCQ_F_THROTTLED; + netif_schedule(sch->dev); +} + +static void +hfsc_schedule_watchdog(struct Qdisc *sch, u64 cur_time) +{ + struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_class *cl; + u64 next_time = 0; + long delay; + + if ((cl = ellist_get_minel(&q->eligible)) != NULL) + next_time = cl->cl_e; + if (q->root.cl_cfmin != 0) { + if (next_time == 0 || next_time > q->root.cl_cfmin) + next_time = q->root.cl_cfmin; + } + ASSERT(next_time != 0); + delay = next_time - cur_time; + delay = PSCHED_US2JIFFIE(delay); + + sch->flags |= TCQ_F_THROTTLED; + mod_timer(&q->wd_timer, jiffies + delay); +} + +static int +hfsc_init_qdisc(struct Qdisc *sch, struct rtattr *opt) +{ + struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct tc_hfsc_qopt *qopt; + unsigned int i; + + if (opt == NULL || RTA_PAYLOAD(opt) < sizeof(*qopt)) + return -EINVAL; + qopt = RTA_DATA(opt); + + memset(q, 0, sizeof(struct hfsc_sched)); + sch->stats.lock = &sch->dev->queue_lock; + + q->defcls = qopt->defcls; + for (i = 0; i < HFSC_HSIZE; i++) + INIT_LIST_HEAD(&q->clhash[i]); + INIT_LIST_HEAD(&q->eligible); + INIT_LIST_HEAD(&q->droplist); + + q->root.refcnt = 1; + q->root.classid = sch->handle; + q->root.sched = q; + q->root.qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); + if (q->root.qdisc == NULL) + q->root.qdisc = &noop_qdisc; + q->root.stats.lock = &sch->dev->queue_lock; + INIT_LIST_HEAD(&q->root.children); + INIT_LIST_HEAD(&q->root.actlist); + + list_add(&q->root.hlist, &q->clhash[hfsc_hash(q->root.classid)]); + + init_timer(&q->wd_timer); + q->wd_timer.function = hfsc_watchdog; + q->wd_timer.data = (unsigned long)sch; + + return 0; +} + +static int +hfsc_change_qdisc(struct Qdisc *sch, struct rtattr *opt) +{ + struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct tc_hfsc_qopt *qopt; + + if (opt == NULL || RTA_PAYLOAD(opt) < sizeof(*qopt)) + return -EINVAL;; + qopt = RTA_DATA(opt); + + sch_tree_lock(sch); + q->defcls = qopt->defcls; + sch_tree_unlock(sch); + + return 0; +} + +static void +hfsc_reset_class(struct hfsc_class *cl) +{ + cl->cl_total = 0; + cl->cl_cumul = 0; + cl->cl_d = 0; + cl->cl_e = 0; + cl->cl_vt = 0; + cl->cl_vtadj = 0; + cl->cl_vtoff = 0; + cl->cl_cvtmin = 0; + cl->cl_cvtmax = 0; + cl->cl_vtperiod = 0; + cl->cl_parentperiod = 0; + cl->cl_f = 0; + cl->cl_myf = 0; + cl->cl_myfadj = 0; + cl->cl_cfmin = 0; + cl->cl_nactive = 0; + INIT_LIST_HEAD(&cl->actlist); + qdisc_reset(cl->qdisc); + + if (cl->cl_flags & HFSC_RSC) + rtsc_init(&cl->cl_deadline, &cl->cl_rsc, 0, 0); + if (cl->cl_flags & HFSC_FSC) + rtsc_init(&cl->cl_virtual, &cl->cl_fsc, 0, 0); + if (cl->cl_flags & HFSC_USC) + rtsc_init(&cl->cl_ulimit, &cl->cl_usc, 0, 0); +} + +static void +hfsc_reset_qdisc(struct Qdisc *sch) +{ + struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_class *cl; + unsigned int i; + + for (i = 0; i < HFSC_HSIZE; i++) { + list_for_each_entry(cl, &q->clhash[i], hlist) + hfsc_reset_class(cl); + } + + INIT_LIST_HEAD(&q->eligible); + INIT_LIST_HEAD(&q->droplist); + q->last_xmit = NULL; + del_timer(&q->wd_timer); + sch->flags &= ~TCQ_F_THROTTLED; + sch->q.qlen = 0; +} + +static void +hfsc_destroy_qdisc(struct Qdisc *sch) +{ + struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_class *cl, *next; + unsigned int i; + + for (i = 0; i < HFSC_HSIZE; i++) { + list_for_each_entry_safe(cl, next, &q->clhash[i], hlist) + hfsc_destroy_class(sch, cl); + } + + del_timer(&q->wd_timer); +} + +static int +hfsc_dump_qdisc(struct Qdisc *sch, struct sk_buff *skb) +{ + struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + unsigned char *b = skb->tail; + struct tc_hfsc_qopt qopt; + + qopt.defcls = q->defcls; + RTA_PUT(skb, TCA_OPTIONS, sizeof(qopt), &qopt); + + sch->stats.qlen = sch->q.qlen; + if (qdisc_copy_stats(skb, &sch->stats) < 0) + goto rtattr_failure; + + return skb->len; + + rtattr_failure: + skb_trim(skb, b - skb->data); + return -1; +} + +static int +hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch) +{ + struct hfsc_class *cl = hfsc_classify(skb, sch); + unsigned int len = skb->len; + int err; + + if (cl == NULL) { + kfree_skb(skb); + sch->stats.drops++; + return NET_XMIT_DROP; + } + + err = cl->qdisc->enqueue(skb, cl->qdisc); + if (unlikely(err != NET_XMIT_SUCCESS)) { + cl->stats.drops++; + sch->stats.drops++; + return err; + } + + if (cl->qdisc->q.qlen == 1) + set_active(cl, len); + + cl->stats.packets++; + cl->stats.bytes += len; + sch->stats.packets++; + sch->stats.bytes += len; + sch->q.qlen++; + + return NET_XMIT_SUCCESS; +} + +static struct sk_buff * +hfsc_dequeue(struct Qdisc *sch) +{ + struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_class *cl; + struct sk_buff *skb; + u64 cur_time; + unsigned int next_len; + int realtime = 0; + + if (sch->q.qlen == 0) + return NULL; + + PSCHED_GET_TIME(cur_time); + + /* + * if there are eligible classes, use real-time criteria. + * find the class with the minimum deadline among + * the eligible classes. + */ + if ((cl = ellist_get_mindl(&q->eligible, cur_time)) != NULL) { + realtime = 1; + } else { + /* + * use link-sharing criteria + * get the class with the minimum vt in the hierarchy + */ + cl = actlist_get_minvt(&q->root, cur_time); + if (cl == NULL) { + sch->stats.overlimits++; + if (!netif_queue_stopped(sch->dev)) + hfsc_schedule_watchdog(sch, cur_time); + return NULL; + } + } + + skb = cl->qdisc->dequeue(cl->qdisc); + if (skb == NULL) { + if (net_ratelimit()) + printk("HFSC: Non-work-conserving qdisc ?\n"); + return NULL; + } + + update_vf(cl, skb->len, cur_time); + if (realtime) + cl->cl_cumul += skb->len; + + if (cl->qdisc->q.qlen != 0) { + if (cl->cl_flags & HFSC_RSC) { + /* update ed */ + next_len = qdisc_peek_len(cl->qdisc); + if (realtime) + update_ed(cl, next_len); + else + update_d(cl, next_len); + } + } else { + /* the class becomes passive */ + set_passive(cl); + } + + q->last_xmit = cl; + sch->flags &= ~TCQ_F_THROTTLED; + sch->q.qlen--; + + return skb; +} + +static int +hfsc_requeue(struct sk_buff *skb, struct Qdisc *sch) +{ + struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_class *cl = q->last_xmit; + unsigned int len = skb->len; + int ret; + + if (cl == NULL) { + kfree_skb(skb); + sch->stats.drops++; + return NET_XMIT_DROP; + } + + ret = cl->qdisc->ops->requeue(skb, cl->qdisc); + if (ret == NET_XMIT_SUCCESS) { + if (cl->qdisc->q.qlen == 1) + set_active(cl, len); + sch->q.qlen++; + } else { + cl->stats.drops++; + sch->stats.drops++; + } + q->last_xmit = NULL; + + return ret; +} + +static unsigned int +hfsc_drop(struct Qdisc *sch) +{ + struct hfsc_sched *q = (struct hfsc_sched *)sch->data; + struct hfsc_class *cl; + unsigned int len; + + list_for_each_entry(cl, &q->droplist, dlist) { + if (cl->qdisc->ops->drop != NULL && + (len = cl->qdisc->ops->drop(cl->qdisc)) > 0) { + if (cl->qdisc->q.qlen == 0) { + update_vf(cl, 0, 0); + set_passive(cl); + } else { + list_move_tail(&cl->dlist, &q->droplist); + } + cl->stats.drops++; + sch->stats.drops++; + sch->q.qlen--; + return len; + } + } + return 0; +} + +static struct Qdisc_class_ops hfsc_class_ops = { + .change = hfsc_change_class, + .delete = hfsc_delete_class, + .graft = hfsc_graft_class, + .leaf = hfsc_class_leaf, + .get = hfsc_get_class, + .put = hfsc_put_class, + .bind_tcf = hfsc_bind_tcf, + .unbind_tcf = hfsc_unbind_tcf, + .tcf_chain = hfsc_tcf_chain, + .dump = hfsc_dump_class, + .walk = hfsc_walk +}; + +struct Qdisc_ops hfsc_qdisc_ops = { + .id = "hfsc", + .init = hfsc_init_qdisc, + .change = hfsc_change_qdisc, + .reset = hfsc_reset_qdisc, + .destroy = hfsc_destroy_qdisc, + .dump = hfsc_dump_qdisc, + .enqueue = hfsc_enqueue, + .dequeue = hfsc_dequeue, + .requeue = hfsc_requeue, + .drop = hfsc_drop, + .cl_ops = &hfsc_class_ops, + .priv_size = sizeof(struct hfsc_sched), + .owner = THIS_MODULE +}; + +static int __init +hfsc_init(void) +{ + return register_qdisc(&hfsc_qdisc_ops); +} + +static void __exit +hfsc_cleanup(void) +{ + unregister_qdisc(&hfsc_qdisc_ops); +} + +MODULE_LICENSE("GPL"); +module_init(hfsc_init); +module_exit(hfsc_cleanup); -- cgit v1.2.3 From aef22e5b8f3374b0552bc80edf82f1093d72dc79 Mon Sep 17 00:00:00 2001 From: David Stevens Date: Wed, 28 Jan 2004 22:58:29 -0800 Subject: [IPV4]: Add per-device sysctl to force IGMP version. --- include/linux/inetdevice.h | 1 + include/linux/sysctl.h | 1 + net/ipv4/devinet.c | 11 ++++++++++- net/ipv4/igmp.c | 12 ++++++++---- 4 files changed, 20 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h index 18913dfaddb1..1c5eb02667bb 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h @@ -21,6 +21,7 @@ struct ipv4_devconf int medium_id; int no_xfrm; int no_policy; + int force_igmp_version; void *sysctl; }; diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 0d5b121f54a0..b8806feac0b5 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -360,6 +360,7 @@ enum NET_IPV4_CONF_MEDIUM_ID=14, NET_IPV4_CONF_NOXFRM=15, NET_IPV4_CONF_NOPOLICY=16, + NET_IPV4_CONF_FORCE_IGMP_VERSION=17, }; /* /proc/sys/net/ipv4/netfilter */ diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 4bdfd7319ae6..4f3415afc983 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1132,7 +1132,7 @@ int ipv4_doint_and_flush_strategy(ctl_table *table, int *name, int nlen, static struct devinet_sysctl_table { struct ctl_table_header *sysctl_header; - ctl_table devinet_vars[17]; + ctl_table devinet_vars[18]; ctl_table devinet_dev[2]; ctl_table devinet_conf_dir[2]; ctl_table devinet_proto_dir[2]; @@ -1269,6 +1269,15 @@ static struct devinet_sysctl_table { .proc_handler = &ipv4_doint_and_flush, .strategy = &ipv4_doint_and_flush_strategy, }, + { + .ctl_name = NET_IPV4_CONF_FORCE_IGMP_VERSION, + .procname = "force_igmp_version", + .data = &ipv4_devconf.force_igmp_version, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &ipv4_doint_and_flush, + .strategy = &ipv4_doint_and_flush_strategy, + }, }, .devinet_dev = { { diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index b1f9f7d62e38..03b1d55c63ff 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -126,10 +126,14 @@ * contradict to specs provided this delay is small enough. */ -#define IGMP_V1_SEEN(in_dev) ((in_dev)->mr_v1_seen && \ - time_before(jiffies, (in_dev)->mr_v1_seen)) -#define IGMP_V2_SEEN(in_dev) ((in_dev)->mr_v2_seen && \ - time_before(jiffies, (in_dev)->mr_v2_seen)) +#define IGMP_V1_SEEN(in_dev) (ipv4_devconf.force_igmp_version == 1 || \ + (in_dev)->cnf.force_igmp_version == 1 || \ + ((in_dev)->mr_v1_seen && \ + time_before(jiffies, (in_dev)->mr_v1_seen))) +#define IGMP_V2_SEEN(in_dev) (ipv4_devconf.force_igmp_version == 2 || \ + (in_dev)->cnf.force_igmp_version == 2 || \ + ((in_dev)->mr_v2_seen && \ + time_before(jiffies, (in_dev)->mr_v2_seen))) static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im); static void igmpv3_del_delrec(struct in_device *in_dev, __u32 multiaddr); -- cgit v1.2.3 From 773be16ac8414a8b10b5e31ea12310d8ca49eb47 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sat, 31 Jan 2004 19:17:59 -0800 Subject: [TCP]: Port 2.4.x version of TCP Westwood support to 2.6.x Original 2.4.x version by Angelo Dell'Aera (buffer@antifork.org) Here is the 2.4 version with some cleanups converted to 2.6. - use tcp_ prefix (dave) - get rid of rwlock not needed (dave) - do some hand optimization of the inline's - don't make init inline - get rid of extra whitespace - eliminate accessor for mss_cache --- include/linux/sysctl.h | 1 + include/linux/tcp.h | 14 +++ include/net/tcp.h | 64 +++++++++++ net/ipv4/sysctl_net_ipv4.c | 8 ++ net/ipv4/tcp_input.c | 268 ++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 352 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index b8806feac0b5..935be9d21b69 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -311,6 +311,7 @@ enum NET_TCP_FRTO=92, NET_TCP_LOW_LATENCY=93, NET_IPV4_IPFRAG_SECRET_INTERVAL=94, + NET_TCP_WESTWOOD=95, }; enum { diff --git a/include/linux/tcp.h b/include/linux/tcp.h index d25e5bd21c4d..1b35358879ce 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -374,6 +374,20 @@ struct tcp_opt { __u32 frto_highmark; /* snd_nxt when RTO occurred */ unsigned long last_synq_overflow; + +/* TCP Westwood structure */ + struct { + __u32 bw_sample; /* bandwidth sample */ + __u32 bw_ns_est; /* first bandwidth estimation..not too smoothed 8) */ + __u32 bw_est; /* bandwidth estimate */ + __u32 rtt_win_sx; /* here starts a new evaluation... */ + __u32 bk; + __u32 snd_una; /* used for evaluating the number of acked bytes */ + __u32 cumul_ack; + __u32 accounted; + __u32 rtt; + __u32 rtt_min; /* minimum observed RTT */ + } westwood; }; /* WARNING: don't change the layout of the members in tcp_sock! */ diff --git a/include/net/tcp.h b/include/net/tcp.h index cec451adf4bf..55c5ea8f16ac 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -579,6 +579,7 @@ extern int sysctl_tcp_adv_win_scale; extern int sysctl_tcp_tw_reuse; extern int sysctl_tcp_frto; extern int sysctl_tcp_low_latency; +extern int sysctl_tcp_westwood; extern atomic_t tcp_memory_allocated; extern atomic_t tcp_sockets_allocated; @@ -2019,4 +2020,67 @@ struct tcp_iter_state { extern int tcp_proc_register(struct tcp_seq_afinfo *afinfo); extern void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo); +/* TCP Westwood functions and constants */ + +#define TCP_WESTWOOD_INIT_RTT (20*HZ) /* maybe too conservative?! */ +#define TCP_WESTWOOD_RTT_MIN (HZ/20) /* 50ms */ + +static inline void tcp_westwood_update_rtt(struct tcp_opt *tp, __u32 rtt_seq) +{ + if (sysctl_tcp_westwood) + tp->westwood.rtt = rtt_seq; +} + +void __tcp_westwood_fast_bw(struct sock *, struct sk_buff *); +void __tcp_westwood_slow_bw(struct sock *, struct sk_buff *); + +static inline void tcp_westwood_fast_bw(struct sock *sk, struct sk_buff *skb) +{ + if (sysctl_tcp_westwood) + __tcp_westwood_fast_bw(sk, skb); +} + +static inline void tcp_westwood_slow_bw(struct sock *sk, struct sk_buff *skb) +{ + if (sysctl_tcp_westwood) + __tcp_westwood_slow_bw(sk, skb); +} + +static inline __u32 __tcp_westwood_bw_rttmin(const struct tcp_opt *tp) +{ + return max((tp->westwood.bw_est) * (tp->westwood.rtt_min) / + (__u32) (tp->mss_cache), + 2U); +} + +static inline __u32 tcp_westwood_bw_rttmin(const struct tcp_opt *tp) +{ + return sysctl_tcp_westwood ? __tcp_westwood_bw_rttmin(tp) : 0; +} + +static inline int tcp_westwood_ssthresh(struct tcp_opt *tp) +{ + __u32 ssthresh = 0; + + if (sysctl_tcp_westwood) { + ssthresh = __tcp_westwood_bw_rttmin(tp); + if (ssthresh) + tp->snd_ssthresh = ssthresh; + } + + return (ssthresh != 0); +} + +static inline int tcp_westwood_cwnd(struct tcp_opt *tp) +{ + __u32 cwnd = 0; + + if (sysctl_tcp_westwood) { + cwnd = __tcp_westwood_bw_rttmin(tp); + if (cwnd) + tp->snd_cwnd = cwnd; + } + + return (cwnd != 0); +} #endif /* _TCP_H */ diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index f1ac4b2130b9..782ac7c19ec3 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -584,6 +584,14 @@ ctl_table ipv4_table[] = { .proc_handler = &proc_dointvec_jiffies, .strategy = &sysctl_jiffies }, + { + .ctl_name = NET_TCP_WESTWOOD, + .procname = "tcp_westwood", + .data = &sysctl_tcp_westwood, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, { .ctl_name = 0 } }; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 5f446e0c6242..f00312f80a94 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -61,6 +61,7 @@ * Panu Kuhlberg: Experimental audit of TCP (re)transmission * engine. Lots of bugs are found. * Pasi Sarolahti: F-RTO for dealing with spurious RTOs + * Angelo Dell'Aera: TCP Westwood+ support */ #include @@ -89,6 +90,7 @@ int sysctl_tcp_stdurg; int sysctl_tcp_rfc1337; int sysctl_tcp_max_orphans = NR_FILE; int sysctl_tcp_frto; +int sysctl_tcp_westwood; #define FLAG_DATA 0x01 /* Incoming frame contained data. */ #define FLAG_WIN_UPDATE 0x02 /* Incoming ACK was a window update. */ @@ -474,6 +476,8 @@ static void tcp_rtt_estimator(struct tcp_opt *tp, __u32 mrtt) tp->mdev_max = tp->rttvar = max(tp->mdev, TCP_RTO_MIN); tp->rtt_seq = tp->snd_nxt; } + + tcp_westwood_update_rtt(tp, tp->srtt >> 3); } /* Calculate rto without backoff. This is the second half of Van Jacobson's @@ -981,7 +985,8 @@ void tcp_enter_frto(struct sock *sk) tp->snd_una == tp->high_seq || (tp->ca_state == TCP_CA_Loss && !tp->retransmits)) { tp->prior_ssthresh = tcp_current_ssthresh(tp); - tp->snd_ssthresh = tcp_recalc_ssthresh(tp); + if (!tcp_westwood_ssthresh(tp)) + tp->snd_ssthresh = tcp_recalc_ssthresh(tp); } /* Have to clear retransmission markers here to keep the bookkeeping @@ -1390,11 +1395,24 @@ static __inline__ void tcp_moderate_cwnd(struct tcp_opt *tp) static void tcp_cwnd_down(struct tcp_opt *tp) { int decr = tp->snd_cwnd_cnt + 1; + __u32 limit; + + /* + * TCP Westwood + * Here limit is evaluated as BWestimation*RTTmin (for obtaining it + * in packets we use mss_cache). If CONFIG_TCP_WESTWOOD is not defined + * westwood_bw_rttmin() returns 0. In such case snd_ssthresh is still + * used as usual. It prevents other strange cases in which BWE*RTTmin + * could assume value 0. It should not happen but... + */ + + if (!(limit = tcp_westwood_bw_rttmin(tp))) + limit = tp->snd_ssthresh/2; tp->snd_cwnd_cnt = decr&1; decr >>= 1; - if (decr && tp->snd_cwnd > tp->snd_ssthresh/2) + if (decr && tp->snd_cwnd > limit) tp->snd_cwnd -= decr; tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp)+1); @@ -1539,7 +1557,10 @@ static int tcp_try_undo_loss(struct sock *sk, struct tcp_opt *tp) static __inline__ void tcp_complete_cwr(struct tcp_opt *tp) { - tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh); + if (tcp_westwood_cwnd(tp)) + tp->snd_ssthresh = tp->snd_cwnd; + else + tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh); tp->snd_cwnd_stamp = tcp_time_stamp; } @@ -2030,6 +2051,240 @@ static void tcp_process_frto(struct sock *sk, u32 prior_snd_una) */ tp->frto_counter = (tp->frto_counter + 1) % 3; } +/* + * TCP Westwood + * Functions needed for estimating bandwidth. + */ + +/* + * This function initializes fields used in TCP Westwood. + * We can't get no information about RTT at this time so + * we are forced to set it to 0. + */ +static void init_westwood(struct sock *sk) +{ + struct tcp_opt *tp = tcp_sk(sk); + + tp->westwood.bw_sample = 0; + tp->westwood.bw_ns_est = 0; + tp->westwood.bw_est = 0; + tp->westwood.accounted = 0; + tp->westwood.cumul_ack = 0; + tp->westwood.rtt_win_sx = tcp_time_stamp; + tp->westwood.rtt = TCP_WESTWOOD_INIT_RTT; + tp->westwood.rtt_min = TCP_WESTWOOD_INIT_RTT; + tp->westwood.snd_una = tp->snd_una; +} + +/* + * @westwood_do_filter + * Low-pass filter. Implemented using constant coeffients. + */ +static inline __u32 westwood_do_filter(__u32 a, __u32 b) +{ + return (((7 * a) + b) >> 3); +} + +static void westwood_filter(struct sock *sk, __u32 delta) +{ + struct tcp_opt *tp = tcp_sk(sk); + __u32 sample = tp->westwood.bk / delta; + + tp->westwood.bw_ns_est = + westwood_do_filter(tp->westwood.bw_ns_est, sample); + tp->westwood.bw_est = + westwood_do_filter(tp->westwood.bw_est, + tp->westwood.bw_ns_est); + tp->westwood.bw_sample = sample; +} + +/* @westwood_update_rttmin + * It is used to update RTTmin. In this case we MUST NOT use + * WESTWOOD_RTT_MIN minimum bound since we could be on a LAN! + */ +static inline __u32 westwood_update_rttmin(struct sock *sk) +{ + struct tcp_opt *tp = tcp_sk(sk); + __u32 rttmin = tp->westwood.rtt_min; + + if (tp->westwood.rtt == 0) + return(rttmin); + + if (tp->westwood.rtt < tp->westwood.rtt_min || !rttmin) + rttmin = tp->westwood.rtt; + + return(rttmin); +} + +/* + * @westwood_acked + * Evaluate increases for dk. It requires no lock since when it is + * called lock should already be held. Be careful about it! + */ +static inline __u32 westwood_acked(struct sock *sk) +{ + struct tcp_opt *tp = tcp_sk(sk); + + return ((tp->snd_una) - (tp->westwood.snd_una)); +} + +/* + * @westwood_new_window + * It evaluates if we are receiving data inside the same RTT window as + * when we started. + * Return value: + * It returns 0 if we are still evaluating samples in the same RTT + * window, 1 if the sample has to be considered in the next window. + */ +static int westwood_new_window(struct sock *sk) +{ + struct tcp_opt *tp = tcp_sk(sk); + __u32 left_bound; + __u32 rtt; + int ret = 0; + + left_bound = tp->westwood.rtt_win_sx; + rtt = max(tp->westwood.rtt, (u32) TCP_WESTWOOD_RTT_MIN); + + /* + * A RTT-window has passed. Be careful since if RTT is less than + * 50ms we don't filter but we continue 'building the sample'. + * This minimum limit was choosen since an estimation on small + * time intervals is better to avoid... + * Obvioulsy on a LAN we reasonably will always have + * right_bound = left_bound + WESTWOOD_RTT_MIN + */ + + if ((left_bound + rtt) < tcp_time_stamp) + ret = 1; + + return ret; +} + +/* + * @westwood_update_window + * It updates RTT evaluation window if it is the right moment to do + * it. If so it calls filter for evaluating bandwidth. Be careful + * about __westwood_update_window() since it is called without + * any form of lock. It should be used only for internal purposes. + * Call westwood_update_window() instead. + */ +static void __westwood_update_window(struct sock *sk, __u32 now) +{ + struct tcp_opt *tp = tcp_sk(sk); + __u32 delta = now - tp->westwood.rtt_win_sx; + + if (!delta) + return; + + if (tp->westwood.rtt) + westwood_filter(sk, delta); + + tp->westwood.bk = 0; + tp->westwood.rtt_win_sx = tcp_time_stamp; +} + + +static void westwood_update_window(struct sock *sk, __u32 now) +{ + if (westwood_new_window(sk)) + __westwood_update_window(sk, now); +} + +/* + * @__westwood_fast_bw + * It is called when we are in fast path. In particular it is called when + * header prediction is successfull. In such case infact update is + * straight forward and doesn't need any particular care. + */ +void __tcp_westwood_fast_bw(struct sock *sk, struct sk_buff *skb) +{ + struct tcp_opt *tp = tcp_sk(sk); + + westwood_update_window(sk, tcp_time_stamp); + + tp->westwood.bk += westwood_acked(sk); + tp->westwood.snd_una = tp->snd_una; + tp->westwood.rtt_min = westwood_update_rttmin(sk); +} + + +/* + * @tcp_westwood_dupack_update + * It updates accounted and cumul_ack when receiving a dupack. + */ + +static void westwood_dupack_update(struct sock *sk) +{ + struct tcp_opt *tp = tcp_sk(sk); + + tp->westwood.accounted += tp->mss_cache; + tp->westwood.cumul_ack = tp->mss_cache; +} + +static inline int westwood_may_change_cumul(struct tcp_opt *tp) +{ + return ((tp->westwood.cumul_ack) > tp->mss_cache); +} + +static inline void westwood_partial_update(struct tcp_opt *tp) +{ + tp->westwood.accounted -= tp->westwood.cumul_ack; + tp->westwood.cumul_ack = tp->mss_cache; +} + +static inline void westwood_complete_update(struct tcp_opt *tp) +{ + tp->westwood.cumul_ack -= tp->westwood.accounted; + tp->westwood.accounted = 0; +} + +/* + * @westwood_acked_count + * This function evaluates cumul_ack for evaluating dk in case of + * delayed or partial acks. + */ +static __u32 westwood_acked_count(struct sock *sk) +{ + struct tcp_opt *tp = tcp_sk(sk); + + tp->westwood.cumul_ack = westwood_acked(sk); + + /* If cumul_ack is 0 this is a dupack since it's not moving + * tp->snd_una. + */ + if (!(tp->westwood.cumul_ack)) + westwood_dupack_update(sk); + + if (westwood_may_change_cumul(tp)) { + /* Partial or delayed ack */ + if ((tp->westwood.accounted) >= (tp->westwood.cumul_ack)) + westwood_partial_update(tp); + else + westwood_complete_update(tp); + } + + tp->westwood.snd_una = tp->snd_una; + + return tp->westwood.cumul_ack; +} + + +/* + * @__westwood_slow_bw + * It is called when something is going wrong..even if there could + * be no problems! Infact a simple delayed packet may trigger a + * dupack. But we need to be careful in such case. + */ +void __tcp_westwood_slow_bw(struct sock *sk, struct sk_buff *skb) +{ + struct tcp_opt *tp = tcp_sk(sk); + + westwood_update_window(sk, tcp_time_stamp); + + tp->westwood.bk += westwood_acked_count(sk); + tp->westwood.rtt_min = westwood_update_rttmin(sk); +} /* This routine deals with incoming acks, but not outgoing ones. */ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag) @@ -2057,6 +2312,7 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag) */ tcp_update_wl(tp, ack, ack_seq); tp->snd_una = ack; + tcp_westwood_fast_bw(sk, skb); flag |= FLAG_WIN_UPDATE; NET_INC_STATS_BH(TCPHPAcks); @@ -2073,6 +2329,8 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag) if (TCP_ECN_rcv_ecn_echo(tp, skb->h.th)) flag |= FLAG_ECE; + + tcp_westwood_slow_bw(sk,skb); } /* We passed data and got it acked, remove any soft error @@ -3866,6 +4124,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, if(tp->af_specific->conn_request(sk, skb) < 0) return 1; + init_westwood(sk); + /* Now we have several options: In theory there is * nothing else in the frame. KA9Q has an option to * send data with the syn, BSD accepts data with the @@ -3887,6 +4147,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, goto discard; case TCP_SYN_SENT: + init_westwood(sk); + queued = tcp_rcv_synsent_state_process(sk, skb, th, len); if (queued >= 0) return queued; -- cgit v1.2.3 From 807adbc535f8ae97c4b71c0ae8b9823ca809558d Mon Sep 17 00:00:00 2001 From: Patrick Mansfield Date: Sun, 1 Feb 2004 22:53:17 -0600 Subject: [PATCH] change scsi_cmd_ioctl to take a gendisk instead of a queue This patch against a recent bk 2.6 changes scsi_cmd_ioctl to take a gendisk as an argument instead of a request_queue_t. This allows scsi char devices to use the scsi_cmd_ioctl interface. In turn, change bio_map_user to also pass a request_queue_t, and add a __bio_add_page helper that takes a request_queue_t. Tested ide cd burning with no problems. If the scsi upper level scsi_cmd_ioctl usage were consolidated in scsi_prep_fn, we could pass a request_queue_t instead of a gendisk to scsi_cmd_ioctl. --- drivers/block/scsi_ioctl.c | 27 +++++++++++++------------ drivers/cdrom/cdrom.c | 2 +- drivers/ide/ide.c | 2 +- drivers/scsi/sd.c | 2 +- fs/bio.c | 49 +++++++++++++++++++++++++--------------------- include/linux/bio.h | 4 ++-- include/linux/blkdev.h | 2 +- 7 files changed, 47 insertions(+), 41 deletions(-) (limited to 'include/linux') diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c index 0c02c5ab3eeb..c1d25f9c1cff 100644 --- a/drivers/block/scsi_ioctl.c +++ b/drivers/block/scsi_ioctl.c @@ -46,14 +46,14 @@ const unsigned char scsi_command_size[8] = #define SCSI_SENSE_BUFFERSIZE 64 #endif -static int blk_do_rq(request_queue_t *q, struct block_device *bdev, +static int blk_do_rq(request_queue_t *q, struct gendisk *bd_disk, struct request *rq) { char sense[SCSI_SENSE_BUFFERSIZE]; DECLARE_COMPLETION(wait); int err = 0; - rq->rq_disk = bdev->bd_disk; + rq->rq_disk = bd_disk; /* * we need an extra reference to the request, so we can look at @@ -142,7 +142,7 @@ static int sg_emulated_host(request_queue_t *q, int *p) return put_user(1, p); } -static int sg_io(request_queue_t *q, struct block_device *bdev, +static int sg_io(request_queue_t *q, struct gendisk *bd_disk, struct sg_io_hdr *hdr) { unsigned long start_time; @@ -190,7 +190,7 @@ static int sg_io(request_queue_t *q, struct block_device *bdev, * first try to map it into a bio. reading from device will * be a write to vm. */ - bio = bio_map_user(bdev, (unsigned long) hdr->dxferp, + bio = bio_map_user(q, NULL, (unsigned long) hdr->dxferp, hdr->dxfer_len, reading); /* @@ -246,7 +246,7 @@ static int sg_io(request_queue_t *q, struct block_device *bdev, * (if he doesn't check that is his problem). * N.B. a non-zero SCSI status is _not_ necessarily an error. */ - blk_do_rq(q, bdev, rq); + blk_do_rq(q, bd_disk, rq); if (bio) bio_unmap_user(bio, reading); @@ -296,7 +296,7 @@ out_buffer: #define READ_DEFECT_DATA_TIMEOUT (60 * HZ ) #define OMAX_SB_LEN 16 /* For backward compatibility */ -static int sg_scsi_ioctl(request_queue_t *q, struct block_device *bdev, +static int sg_scsi_ioctl(request_queue_t *q, struct gendisk *bd_disk, Scsi_Ioctl_Command *sic) { struct request *rq; @@ -369,7 +369,7 @@ static int sg_scsi_ioctl(request_queue_t *q, struct block_device *bdev, rq->data_len = bytes; rq->flags |= REQ_BLOCK_PC; - blk_do_rq(q, bdev, rq); + blk_do_rq(q, bd_disk, rq); err = rq->errors & 0xff; /* only 8 bit SCSI status */ if (err) { if (rq->sense_len && rq->sense) { @@ -389,13 +389,13 @@ error: return err; } -int scsi_cmd_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg) +int scsi_cmd_ioctl(struct gendisk *bd_disk, unsigned int cmd, unsigned long arg) { request_queue_t *q; struct request *rq; int close = 0, err; - q = bdev_get_queue(bdev); + q = bd_disk->queue; if (!q) return -ENXIO; @@ -446,7 +446,7 @@ int scsi_cmd_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long ar old_cdb = hdr.cmdp; hdr.cmdp = cdb; - err = sg_io(q, bdev, &hdr); + err = sg_io(q, bd_disk, &hdr); hdr.cmdp = old_cdb; if (copy_to_user((struct sg_io_hdr *) arg, &hdr, sizeof(hdr))) @@ -493,7 +493,7 @@ int scsi_cmd_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long ar hdr.timeout = cgc.timeout; hdr.cmdp = cgc.cmd; hdr.cmd_len = sizeof(cgc.cmd); - err = sg_io(q, bdev, &hdr); + err = sg_io(q, bd_disk, &hdr); if (hdr.status) err = -EIO; @@ -514,7 +514,8 @@ int scsi_cmd_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long ar if (!arg) break; - err = sg_scsi_ioctl(q, bdev, (Scsi_Ioctl_Command *)arg); + err = sg_scsi_ioctl(q, bd_disk, + (Scsi_Ioctl_Command *)arg); break; case CDROMCLOSETRAY: close = 1; @@ -528,7 +529,7 @@ int scsi_cmd_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long ar rq->cmd[0] = GPCMD_START_STOP_UNIT; rq->cmd[4] = 0x02 + (close != 0); rq->cmd_len = 6; - err = blk_do_rq(q, bdev, rq); + err = blk_do_rq(q, bd_disk, rq); blk_put_request(rq); break; default: diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 54ac0ba508be..b04475be97c4 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -1773,7 +1773,7 @@ int cdrom_ioctl(struct cdrom_device_info *cdi, struct inode *ip, int ret; /* Try the generic SCSI command ioctl's first.. */ - ret = scsi_cmd_ioctl(ip->i_bdev, cmd, arg); + ret = scsi_cmd_ioctl(ip->i_bdev->bd_disk, cmd, arg); if (ret != -ENOTTY) return ret; diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index bf2282aa9c7a..36a86e5676b9 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -1707,7 +1707,7 @@ int generic_ide_ioctl(struct block_device *bdev, unsigned int cmd, case CDROMEJECT: case CDROMCLOSETRAY: - return scsi_cmd_ioctl(bdev, cmd, arg); + return scsi_cmd_ioctl(bdev->bd_disk, cmd, arg); case HDIO_GET_BUSSTATE: if (!capable(CAP_SYS_ADMIN)) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 327f2549fdd7..8a422f6aa44a 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -554,7 +554,7 @@ static int sd_ioctl(struct inode * inode, struct file * filp, case SCSI_IOCTL_GET_BUS_NUMBER: return scsi_ioctl(sdp, cmd, (void *)arg); default: - error = scsi_cmd_ioctl(bdev, cmd, arg); + error = scsi_cmd_ioctl(disk, cmd, arg); if (error != -ENOTTY) return error; } diff --git a/fs/bio.c b/fs/bio.c index 744bd1217e96..0dc95439da07 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -281,23 +281,9 @@ int bio_get_nr_vecs(struct block_device *bdev) return nr_pages; } -/** - * bio_add_page - attempt to add page to bio - * @bio: destination bio - * @page: page to add - * @len: vec entry length - * @offset: vec entry offset - * - * Attempt to add a page to the bio_vec maplist. This can fail for a - * number of reasons, such as the bio being full or target block - * device limitations. The target block device must allow bio's - * smaller than PAGE_SIZE, so it is always possible to add a single - * page to an empty bio. - */ -int bio_add_page(struct bio *bio, struct page *page, unsigned int len, - unsigned int offset) +static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page + *page, unsigned int len, unsigned int offset) { - request_queue_t *q = bdev_get_queue(bio->bi_bdev); int retried_segments = 0; struct bio_vec *bvec; @@ -362,14 +348,33 @@ int bio_add_page(struct bio *bio, struct page *page, unsigned int len, return len; } -static struct bio *__bio_map_user(struct block_device *bdev, +/** + * bio_add_page - attempt to add page to bio + * @bio: destination bio + * @page: page to add + * @len: vec entry length + * @offset: vec entry offset + * + * Attempt to add a page to the bio_vec maplist. This can fail for a + * number of reasons, such as the bio being full or target block + * device limitations. The target block device must allow bio's + * smaller than PAGE_SIZE, so it is always possible to add a single + * page to an empty bio. + */ +int bio_add_page(struct bio *bio, struct page *page, unsigned int len, + unsigned int offset) +{ + return __bio_add_page(bdev_get_queue(bio->bi_bdev), bio, page, + len, offset); +} + +static struct bio *__bio_map_user(request_queue_t *q, struct block_device *bdev, unsigned long uaddr, unsigned int len, int write_to_vm) { unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT; unsigned long start = uaddr >> PAGE_SHIFT; const int nr_pages = end - start; - request_queue_t *q = bdev_get_queue(bdev); int ret, offset, i; struct page **pages; struct bio *bio; @@ -412,7 +417,7 @@ static struct bio *__bio_map_user(struct block_device *bdev, /* * sorry... */ - if (bio_add_page(bio, pages[i], bytes, offset) < bytes) + if (__bio_add_page(q, bio, pages[i], bytes, offset) < bytes) break; len -= bytes; @@ -451,12 +456,12 @@ out: * Map the user space address into a bio suitable for io to a block * device. */ -struct bio *bio_map_user(struct block_device *bdev, unsigned long uaddr, - unsigned int len, int write_to_vm) +struct bio *bio_map_user(request_queue_t *q, struct block_device *bdev, + unsigned long uaddr, unsigned int len, int write_to_vm) { struct bio *bio; - bio = __bio_map_user(bdev, uaddr, len, write_to_vm); + bio = __bio_map_user(q, bdev, uaddr, len, write_to_vm); if (bio) { /* diff --git a/include/linux/bio.h b/include/linux/bio.h index d3b4e9ed4052..86eed2d34407 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -241,8 +241,8 @@ extern inline void bio_init(struct bio *); extern int bio_add_page(struct bio *, struct page *, unsigned int,unsigned int); extern int bio_get_nr_vecs(struct block_device *); -extern struct bio *bio_map_user(struct block_device *, unsigned long, - unsigned int, int); +extern struct bio *bio_map_user(struct request_queue *, struct block_device *, + unsigned long, unsigned int, int); extern void bio_unmap_user(struct bio *, int); extern void bio_set_pages_dirty(struct bio *bio); extern void bio_check_pages_dirty(struct bio *bio); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index d0ba766eca75..e4aa5cfac38c 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -508,7 +508,7 @@ extern int blk_remove_plug(request_queue_t *); extern void blk_recount_segments(request_queue_t *, struct bio *); extern inline int blk_phys_contig_segment(request_queue_t *q, struct bio *, struct bio *); extern inline int blk_hw_contig_segment(request_queue_t *q, struct bio *, struct bio *); -extern int scsi_cmd_ioctl(struct block_device *, unsigned int, unsigned long); +extern int scsi_cmd_ioctl(struct gendisk *, unsigned int, unsigned long); extern void blk_start_queue(request_queue_t *q); extern void blk_stop_queue(request_queue_t *q); extern void __blk_stop_queue(request_queue_t *q); -- cgit v1.2.3 From 93a2d85f93059cb8e534594281217ddc8b84dcfa Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:31:40 -0800 Subject: [PATCH] VT locking fixes From: Benjamin Herrenschmidt - Make sure that all console operations are approriately protected under console_sem. - Adds checks to make sure that people are taking console_sem when it is expected to be held. --- drivers/char/selection.c | 4 ++ drivers/char/tty_io.c | 7 ++- drivers/char/vt.c | 157 +++++++++++++++++++++++++++++++++-------------- drivers/char/vt_ioctl.c | 61 +++++++++++++----- include/linux/console.h | 8 +++ kernel/power/console.c | 16 +++-- kernel/printk.c | 20 ++++++ 7 files changed, 205 insertions(+), 68 deletions(-) (limited to 'include/linux') diff --git a/drivers/char/selection.c b/drivers/char/selection.c index 4f35e17b54d3..74e78b721842 100644 --- a/drivers/char/selection.c +++ b/drivers/char/selection.c @@ -24,6 +24,7 @@ #include #include #include +#include #ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) @@ -290,7 +291,10 @@ int paste_selection(struct tty_struct *tty) int pasted = 0, count; DECLARE_WAITQUEUE(wait, current); + acquire_console_sem(); poke_blanked_console(); + release_console_sem(); + add_wait_queue(&vt->paste_wait, &wait); while (sel_buffer && sel_buffer_lth > pasted) { set_current_state(TASK_INTERRUPTIBLE); diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 93a2e1702f42..963f6fb2b5dd 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1484,7 +1484,12 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, #ifdef CONFIG_VT if (tty->driver->type == TTY_DRIVER_TYPE_CONSOLE) { unsigned int currcons = tty->index; - if (vc_resize(currcons, tmp_ws.ws_col, tmp_ws.ws_row)) + int rc; + + acquire_console_sem(); + rc = vc_resize(currcons, tmp_ws.ws_col, tmp_ws.ws_row); + release_console_sem(); + if (rc) return -ENXIO; } #endif diff --git a/drivers/char/vt.c b/drivers/char/vt.c index dcb286822cbb..bcd650e200e4 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -148,7 +148,6 @@ static const struct consw *con_driver_map[MAX_NR_CONSOLES]; static int con_open(struct tty_struct *, struct file *); static void vc_init(unsigned int console, unsigned int rows, unsigned int cols, int do_clear); -static void blank_screen(unsigned long dummy); static void gotoxy(int currcons, int new_x, int new_y); static void save_cur(int currcons); static void reset_terminal(int currcons, int do_clear); @@ -156,8 +155,8 @@ static void con_flush_chars(struct tty_struct *tty); static void set_vesa_blanking(unsigned long arg); static void set_cursor(int currcons); static void hide_cursor(int currcons); -static void unblank_screen_t(unsigned long dummy); static void console_callback(void *ignored); +static void blank_screen_t(unsigned long dummy); static int printable; /* Is console ready for printing? */ @@ -214,6 +213,13 @@ static int scrollback_delta; int (*console_blank_hook)(int); static struct timer_list console_timer; +static int blank_state; +static int blank_timer_expired; +enum { + blank_off = 0, + blank_normal_wait, + blank_vesa_wait, +}; /* * Low-Level Functions @@ -337,6 +343,8 @@ static void do_update_region(int currcons, unsigned long start, int count) void update_region(int currcons, unsigned long start, int count) { + WARN_CONSOLE_UNLOCKED(); + if (DO_UPDATE) { hide_cursor(currcons); do_update_region(currcons, start, count); @@ -400,6 +408,8 @@ void invert_screen(int currcons, int offset, int count, int viewed) { unsigned short *p; + WARN_CONSOLE_UNLOCKED(); + count /= 2; p = screenpos(currcons, offset, viewed); if (sw->con_invert_region) @@ -445,6 +455,8 @@ void complement_pos(int currcons, int offset) static unsigned short old; static unsigned short oldx, oldy; + WARN_CONSOLE_UNLOCKED(); + if (p) { scr_writew(old, p); if (DO_UPDATE) @@ -564,6 +576,8 @@ static void set_cursor(int currcons) static void set_origin(int currcons) { + WARN_CONSOLE_UNLOCKED(); + if (!IS_VISIBLE || !sw->con_set_origin || !sw->con_set_origin(vc_cons[currcons].d)) @@ -575,6 +589,8 @@ static void set_origin(int currcons) static inline void save_screen(int currcons) { + WARN_CONSOLE_UNLOCKED(); + if (sw->con_save_screen) sw->con_save_screen(vc_cons[currcons].d); } @@ -588,6 +604,8 @@ void redraw_screen(int new_console, int is_switch) int redraw = 1; int currcons, old_console; + WARN_CONSOLE_UNLOCKED(); + if (!vc_cons_allocated(new_console)) { /* strange ... */ /* printk("redraw_screen: tty %d not allocated ??\n", new_console+1); */ @@ -665,6 +683,8 @@ static void visual_init(int currcons, int init) int vc_allocate(unsigned int currcons) /* return 0 on success */ { + WARN_CONSOLE_UNLOCKED(); + if (currcons >= MAX_NR_CONSOLES) return -ENXIO; if (!vc_cons[currcons].d) { @@ -731,6 +751,8 @@ int vc_resize(int currcons, unsigned int cols, unsigned int lines) unsigned int new_cols, new_rows, new_row_size, new_screen_size; unsigned short *newscreen; + WARN_CONSOLE_UNLOCKED(); + if (!vc_cons_allocated(currcons)) return -ENXIO; @@ -817,7 +839,8 @@ int vc_resize(int currcons, unsigned int cols, unsigned int lines) void vc_disallocate(unsigned int currcons) { - acquire_console_sem(); + WARN_CONSOLE_UNLOCKED(); + if (vc_cons_allocated(currcons)) { sw->con_deinit(vc_cons[currcons].d); if (kmalloced) @@ -826,7 +849,6 @@ void vc_disallocate(unsigned int currcons) kfree(vc_cons[currcons].d); vc_cons[currcons].d = NULL; } - release_console_sem(); } /* @@ -2081,6 +2103,10 @@ static void console_callback(void *ignored) sw->con_scrolldelta(vc_cons[currcons].d, scrollback_delta); scrollback_delta = 0; } + if (blank_timer_expired) { + do_blank_screen(0); + blank_timer_expired = 0; + } release_console_sem(); } @@ -2414,7 +2440,9 @@ static int con_open(struct tty_struct *tty, struct file * filp) currcons = tty->index; + acquire_console_sem(); i = vc_allocate(currcons); + release_console_sem(); if (i) return i; @@ -2480,16 +2508,20 @@ static int __init con_init(void) const char *display_desc = NULL; unsigned int currcons = 0; + acquire_console_sem(); + if (conswitchp) display_desc = conswitchp->con_startup(); if (!display_desc) { fg_console = 0; + release_console_sem(); return 0; } init_timer(&console_timer); - console_timer.function = blank_screen; + console_timer.function = blank_screen_t; if (blankinterval) { + blank_state = blank_normal_wait; mod_timer(&console_timer, jiffies + blankinterval); } @@ -2520,6 +2552,8 @@ static int __init con_init(void) printable = 1; printk("\n"); + release_console_sem(); + #ifdef CONFIG_VT_CONSOLE register_console(&vt_console_driver); #endif @@ -2599,8 +2633,13 @@ void take_over_console(const struct consw *csw, int first, int last, int deflt) int i, j = -1; const char *desc; + acquire_console_sem(); + desc = csw->con_startup(); - if (!desc) return; + if (!desc) { + release_console_sem(); + return; + } if (deflt) conswitchp = csw; @@ -2640,6 +2679,8 @@ void take_over_console(const struct consw *csw, int first, int last, int deflt) desc, vc_cons[j].d->vc_cols, vc_cons[j].d->vc_rows); else printk("to %s\n", desc); + + release_console_sem(); } void give_up_console(const struct consw *csw) @@ -2688,23 +2729,24 @@ static void vesa_powerdown(void) } } -/* - * This is a timer handler - */ -static void vesa_powerdown_screen(unsigned long dummy) -{ - console_timer.function = unblank_screen_t; - - vesa_powerdown(); -} - -static void timer_do_blank_screen(int entering_gfx, int from_timer_handler) +void do_blank_screen(int entering_gfx) { int currcons = fg_console; int i; - if (console_blanked) + WARN_CONSOLE_UNLOCKED(); + + if (console_blanked) { + if (blank_state == blank_vesa_wait) { + blank_state = blank_off; + vesa_powerdown(); + + } return; + } + if (blank_state != blank_normal_wait) + return; + blank_state = blank_off; /* entering graphics mode? */ if (entering_gfx) { @@ -2723,9 +2765,8 @@ static void timer_do_blank_screen(int entering_gfx, int from_timer_handler) } hide_cursor(currcons); - if (!from_timer_handler) - del_timer_sync(&console_timer); - console_timer.function = unblank_screen_t; + del_timer_sync(&console_timer); + blank_timer_expired = 0; save_screen(currcons); /* In case we need to reset origin, blanking hook returns 1 */ @@ -2738,7 +2779,7 @@ static void timer_do_blank_screen(int entering_gfx, int from_timer_handler) return; if (vesa_off_interval) { - console_timer.function = vesa_powerdown_screen; + blank_state = blank_vesa_wait, mod_timer(&console_timer, jiffies + vesa_off_interval); } @@ -2746,18 +2787,6 @@ static void timer_do_blank_screen(int entering_gfx, int from_timer_handler) sw->con_blank(vc_cons[currcons].d, vesa_blank_mode + 1); } -void do_blank_screen(int entering_gfx) -{ - timer_do_blank_screen(entering_gfx, 0); -} - -/* - * This is a timer handler - */ -static void unblank_screen_t(unsigned long dummy) -{ - unblank_screen(); -} /* * Called by timer as well as from vt_console_driver @@ -2766,6 +2795,8 @@ void unblank_screen(void) { int currcons; + WARN_CONSOLE_UNLOCKED(); + ignore_poke = 0; if (!console_blanked) return; @@ -2778,9 +2809,9 @@ void unblank_screen(void) if (vcmode != KD_TEXT) return; /* but leave console_blanked != 0 */ - console_timer.function = blank_screen; if (blankinterval) { mod_timer(&console_timer, jiffies + blankinterval); + blank_state = blank_normal_wait; } console_blanked = 0; @@ -2794,23 +2825,33 @@ void unblank_screen(void) } /* - * This is both a user-level callable and a timer handler + * We defer the timer blanking to work queue so it can take the console semaphore + * (console operations can still happen at irq time, but only from printk which + * has the console semaphore. Not perfect yet, but better than no locking */ -static void blank_screen(unsigned long dummy) +static void blank_screen_t(unsigned long dummy) { - timer_do_blank_screen(0, 1); + blank_timer_expired = 1; + schedule_work(&console_work); } void poke_blanked_console(void) { + WARN_CONSOLE_UNLOCKED(); + + /* This isn't perfectly race free, but a race here would be mostly harmless, + * at worse, we'll do a spurrious blank and it's unlikely + */ del_timer(&console_timer); + blank_timer_expired = 0; + if (ignore_poke || !vt_cons[fg_console] || vt_cons[fg_console]->vc_mode == KD_GRAPHICS) return; - if (console_blanked) { - console_timer.function = unblank_screen_t; - mod_timer(&console_timer, jiffies); /* Now */ - } else if (blankinterval) { + if (console_blanked) + unblank_screen(); + else if (blankinterval) { mod_timer(&console_timer, jiffies + blankinterval); + blank_state = blank_normal_wait; } } @@ -2820,6 +2861,8 @@ void poke_blanked_console(void) void set_palette(int currcons) { + WARN_CONSOLE_UNLOCKED(); + if (vcmode != KD_GRAPHICS) sw->con_set_palette(vc_cons[currcons].d, color_table); } @@ -2828,6 +2871,8 @@ static int set_get_cmap(unsigned char *arg, int set) { int i, j, k; + WARN_CONSOLE_UNLOCKED(); + for (i = 0; i < 16; i++) if (set) { get_user(default_red[i], arg++); @@ -2859,12 +2904,24 @@ static int set_get_cmap(unsigned char *arg, int set) int con_set_cmap(unsigned char *arg) { - return set_get_cmap (arg,1); + int rc; + + acquire_console_sem(); + rc = set_get_cmap (arg,1); + release_console_sem(); + + return rc; } int con_get_cmap(unsigned char *arg) { - return set_get_cmap (arg,0); + int rc; + + acquire_console_sem(); + rc = set_get_cmap (arg,0); + release_console_sem(); + + return rc; } void reset_palette(int currcons) @@ -2938,8 +2995,12 @@ int con_font_op(int currcons, struct console_font_op *op) set = 1; } else if (op->op == KD_FONT_OP_GET) set = 0; - else - return sw->con_font_op(vc_cons[currcons].d, op); + else { + acquire_console_sem(); + rc = sw->con_font_op(vc_cons[currcons].d, op); + release_console_sem(); + return rc; + } if (op->data) { temp = kmalloc(size, GFP_KERNEL); if (!temp) @@ -3034,10 +3095,14 @@ static int pm_con_request(struct pm_dev *dev, pm_request_t rqst, void *data) switch (rqst) { case PM_RESUME: + acquire_console_sem(); unblank_screen(); + release_console_sem(); break; case PM_SUSPEND: + acquire_console_sem(); do_blank_screen(0); + release_console_sem(); break; } return 0; diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index 1412a620432d..52ffc976fa6d 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c @@ -470,6 +470,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, * currently, setting the mode from KD_TEXT to KD_GRAPHICS * doesn't do a whole lot. i'm not sure if it should do any * restoration of modes or what... + * + * XXX It should at least call into the driver, fbdev's definitely + * need to restore their engine state. --BenH */ if (!perm) return -EPERM; @@ -492,10 +495,12 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, /* * explicitly blank/unblank the screen if switching modes */ + acquire_console_sem(); if (arg == KD_TEXT) unblank_screen(); else do_blank_screen(1); + release_console_sem(); return 0; case KDGETMODE: @@ -665,18 +670,29 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, return -EFAULT; if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS) return -EINVAL; + acquire_console_sem(); vt_cons[console]->vt_mode = tmp; /* the frsig is ignored, so we set it to 0 */ vt_cons[console]->vt_mode.frsig = 0; vt_cons[console]->vt_pid = current->pid; /* no switch is required -- saw@shade.msu.ru */ vt_cons[console]->vt_newvt = -1; + release_console_sem(); return 0; } case VT_GETMODE: - return copy_to_user((void*)arg, &(vt_cons[console]->vt_mode), - sizeof(struct vt_mode)) ? -EFAULT : 0; + { + struct vt_mode tmp; + int rc; + + acquire_console_sem(); + memcpy(&tmp, &vt_cons[console]->vt_mode, sizeof(struct vt_mode)); + release_console_sem(); + + rc = copy_to_user((void*)arg, &tmp, sizeof(struct vt_mode)); + return rc ? -EFAULT : 0; + } /* * Returns global vt state. Note that VT 0 is always open, since @@ -718,7 +734,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, if (arg == 0 || arg > MAX_NR_CONSOLES) return -ENXIO; arg--; + acquire_console_sem(); i = vc_allocate(arg); + release_console_sem(); if (i) return i; set_console(arg); @@ -768,17 +786,20 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, * The current vt has been released, so * complete the switch. */ - int newvt = vt_cons[console]->vt_newvt; + int newvt; + acquire_console_sem(); + newvt = vt_cons[console]->vt_newvt; vt_cons[console]->vt_newvt = -1; i = vc_allocate(newvt); - if (i) + if (i) { + release_console_sem(); return i; + } /* * When we actually do the console switch, * make sure we are atomic with respect to * other console switches.. */ - acquire_console_sem(); complete_change_console(newvt); release_console_sem(); } @@ -806,16 +827,21 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, return -ENXIO; if (arg == 0) { /* disallocate all unused consoles, but leave 0 */ - for (i=1; iv_rows) || get_user(cc, &vtsizes->v_cols)) return -EFAULT; - for (i = 0; i < MAX_NR_CONSOLES; i++) + for (i = 0; i < MAX_NR_CONSOLES; i++) { + acquire_console_sem(); vc_resize(i, cc, ll); + release_console_sem(); + } return 0; } @@ -870,11 +899,13 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, for (i = 0; i < MAX_NR_CONSOLES; i++) { if (!vc_cons[i].d) continue; + acquire_console_sem(); if (vlin) vc_cons[i].d->vc_scan_lines = vlin; if (clin) vc_cons[i].d->vc_font.height = clin; vc_resize(i, cc, ll); + release_console_sem(); } return 0; } diff --git a/include/linux/console.h b/include/linux/console.h index 6db0056fb4c9..f6ff116ccfb3 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -102,6 +102,14 @@ extern void acquire_console_sem(void); extern void release_console_sem(void); extern void console_conditional_schedule(void); extern void console_unblank(void); +extern int is_console_locked(void); + +/* Some debug stub to catch some of the obvious races in the VT code */ +#if 1 +#define WARN_CONSOLE_UNLOCKED() WARN_ON(!is_console_locked() && !oops_in_progress) +#else +#define WARN_CONSOLE_UNLOCKED() +#endif /* VESA Blanking Levels */ #define VESA_NO_BLANKING 0 diff --git a/kernel/power/console.c b/kernel/power/console.c index c8a48236619b..00b390d7a5ad 100644 --- a/kernel/power/console.c +++ b/kernel/power/console.c @@ -6,6 +6,7 @@ #include #include +#include #include "power.h" static int new_loglevel = 10; @@ -18,14 +19,20 @@ int pm_prepare_console(void) console_loglevel = new_loglevel; #ifdef SUSPEND_CONSOLE + acquire_console_sem(); + orig_fgconsole = fg_console; - if (vc_allocate(SUSPEND_CONSOLE)) + if (vc_allocate(SUSPEND_CONSOLE)) { /* we can't have a free VC for now. Too bad, * we don't want to mess the screen for now. */ + release_console_sem(); return 1; + } set_console(SUSPEND_CONSOLE); + release_console_sem(); + if (vt_waitactive(SUSPEND_CONSOLE)) { pr_debug("Suspend: Can't switch VCs."); return 1; @@ -40,12 +47,9 @@ void pm_restore_console(void) { console_loglevel = orig_loglevel; #ifdef SUSPEND_CONSOLE + acquire_console_sem(); set_console(orig_fgconsole); - - /* FIXME: - * This following part is left over from swsusp. Is it really needed? - */ - update_screen(fg_console); + release_console_sem(); #endif return; } diff --git a/kernel/printk.c b/kernel/printk.c index 22ec5a6b34b9..90be371e4842 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -62,6 +62,15 @@ int oops_in_progress; */ static DECLARE_MUTEX(console_sem); struct console *console_drivers; +/* + * This is used for debugging the mess that is the VT code by + * keeping track if we have the console semaphore held. It's + * definitely not the perfect debug tool (we don't know if _WE_ + * hold it are racing, but it helps tracking those weird code + * path in the console code where we end up in places I want + * locked without the console sempahore held + */ +static int console_locked; /* * logbuf_lock protects log_buf, log_start, log_end, con_start and logged_chars @@ -524,6 +533,7 @@ asmlinkage int printk(const char *fmt, ...) goto out; } if (!down_trylock(&console_sem)) { + console_locked = 1; /* * We own the drivers. We can drop the spinlock and let * release_console_sem() print the text @@ -557,10 +567,17 @@ void acquire_console_sem(void) if (in_interrupt()) BUG(); down(&console_sem); + console_locked = 1; console_may_schedule = 1; } EXPORT_SYMBOL(acquire_console_sem); +int is_console_locked(void) +{ + return console_locked; +} +EXPORT_SYMBOL(is_console_locked); + /** * release_console_sem - unlock the console system * @@ -592,12 +609,14 @@ void release_console_sem(void) spin_unlock_irqrestore(&logbuf_lock, flags); call_console_drivers(_con_start, _log_end); } + console_locked = 0; console_may_schedule = 0; up(&console_sem); spin_unlock_irqrestore(&logbuf_lock, flags); if (wake_klogd && !oops_in_progress && waitqueue_active(&log_wait)) wake_up_interruptible(&log_wait); } +EXPORT_SYMBOL(release_console_sem); /** console_conditional_schedule - yield the CPU if required * @@ -633,6 +652,7 @@ void console_unblank(void) */ if (down_trylock(&console_sem) != 0) return; + console_locked = 1; console_may_schedule = 0; for (c = console_drivers; c != NULL; c = c->next) if ((c->flags & CON_ENABLED) && c->unblank) -- cgit v1.2.3 From 5d79075199b4c0891fc8390d23c573825ca28deb Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:31:50 -0800 Subject: [PATCH] lock_cpu_hotplug only if CONFIG_CPU_HOTPLUG From: Rusty Russell The cpucontrol mutex is not required when no cpus can go up and down. Andrew wrote a wrapper for it to avoid #ifdefs, this expands that to only be defined for CONFIG_HOTPLUG_CPU, and uses it everywhere. The only downside is that the cpucontrol lock was overloaded by my recent patch to net/core/flow.c to protect it from reentrance, so this reintroduces the local flow_flush_sem. This code isn't speed critical, so taking two locks when CONFIG_HOTPLUG_CPU=y is not really an issue. --- include/linux/cpu.h | 14 ++++++++------ kernel/module.c | 6 +++--- net/core/flow.c | 6 ++++-- 3 files changed, 15 insertions(+), 11 deletions(-) (limited to 'include/linux') diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 02579ec6b99c..5ecc291dc138 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -38,9 +38,6 @@ extern void unregister_cpu_notifier(struct notifier_block *nb); int cpu_up(unsigned int cpu); -#define lock_cpu_hotplug() down(&cpucontrol) -#define unlock_cpu_hotplug() up(&cpucontrol) - #else static inline int register_cpu_notifier(struct notifier_block *nb) @@ -51,12 +48,17 @@ static inline void unregister_cpu_notifier(struct notifier_block *nb) { } -#define lock_cpu_hotplug() do { } while (0) -#define unlock_cpu_hotplug() do { } while (0) - #endif /* CONFIG_SMP */ extern struct sysdev_class cpu_sysdev_class; +#ifdef CONFIG_HOTPLUG_CPU /* Stop CPUs going up and down. */ extern struct semaphore cpucontrol; +#define lock_cpu_hotplug() down(&cpucontrol) +#define unlock_cpu_hotplug() up(&cpucontrol) +#else +#define lock_cpu_hotplug() do { } while (0) +#define unlock_cpu_hotplug() do { } while (0) +#endif + #endif /* _LINUX_CPU_H_ */ diff --git a/kernel/module.c b/kernel/module.c index fc934874c881..a51fa89ed1a1 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -554,7 +554,7 @@ static int stop_refcounts(void) stopref_state = STOPREF_WAIT; /* No CPUs can come up or down during this. */ - down(&cpucontrol); + lock_cpu_hotplug(); for (i = 0; i < NR_CPUS; i++) { if (i == cpu || !cpu_online(i)) @@ -572,7 +572,7 @@ static int stop_refcounts(void) /* If some failed, kill them all. */ if (ret < 0) { stopref_set_state(STOPREF_EXIT, 1); - up(&cpucontrol); + unlock_cpu_hotplug(); return ret; } @@ -595,7 +595,7 @@ static void restart_refcounts(void) stopref_set_state(STOPREF_EXIT, 0); local_irq_enable(); preempt_enable(); - up(&cpucontrol); + unlock_cpu_hotplug(); } #else /* ...!SMP */ static inline int stop_refcounts(void) diff --git a/net/core/flow.c b/net/core/flow.c index f13a1752b603..cef037afdf41 100644 --- a/net/core/flow.c +++ b/net/core/flow.c @@ -283,10 +283,11 @@ static void flow_cache_flush_per_cpu(void *data) void flow_cache_flush(void) { struct flow_flush_info info; + static DECLARE_MUTEX(flow_flush_sem); - /* Don't want cpus going down or up during this, also protects - * against multiple callers. */ + /* Don't want cpus going down or up during this. */ lock_cpu_hotplug(); + down(&flow_flush_sem); atomic_set(&info.cpuleft, num_online_cpus()); init_completion(&info.completion); @@ -296,6 +297,7 @@ void flow_cache_flush(void) local_bh_enable(); wait_for_completion(&info.completion); + up(&flow_flush_sem); unlock_cpu_hotplug(); } -- cgit v1.2.3 From d75cb1840b2c95fcfa740a9e6b350ae44c9fbb46 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:32:27 -0800 Subject: [PATCH] Fix more gcc 3.4 warnings From: Andi Kleen Just many more warning fixes for a gcc 3.4 snapshot. It warns for a lot of things now, e.g. for ?: and ({ ... }) and casts as lvalues. And for functions marked inline in headers, but no body. Actually there are more warnings, i stopped fixing at some point. Some of the warnings seem to be dubious (e.g. the binfmt_elf.c one, which looks more like a compiler bug to me) I also fixed the _exit() prototype to be void because gcc was complaining about this. --- drivers/ieee1394/highlevel.c | 4 ++-- fs/compat_ioctl.c | 4 +++- fs/ext3/namei.c | 2 +- fs/readdir.c | 4 ++-- include/asm-i386/apic.h | 2 +- include/asm-i386/hw_irq.h | 2 +- include/asm-i386/unistd.h | 2 +- include/linux/efi.h | 4 ++-- include/linux/reiserfs_fs.h | 18 +++++++++--------- include/linux/sched.h | 2 +- kernel/fork.c | 2 +- lib/crc32.c | 16 ++++++++++++---- 12 files changed, 36 insertions(+), 26 deletions(-) (limited to 'include/linux') diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c index 77c3623c00ce..f28c339d6267 100644 --- a/drivers/ieee1394/highlevel.c +++ b/drivers/ieee1394/highlevel.c @@ -521,7 +521,7 @@ int highlevel_read(struct hpsb_host *host, int nodeid, void *data, rcode = RCODE_TYPE_ERROR; } - (u8 *)data += partlength; + data += partlength; length -= partlength; addr += partlength; @@ -567,7 +567,7 @@ int highlevel_write(struct hpsb_host *host, int nodeid, int destid, rcode = RCODE_TYPE_ERROR; } - (u8 *)data += partlength; + data += partlength; length -= partlength; addr += partlength; diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index b2048a804995..a6c74193ba60 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -2112,6 +2112,7 @@ static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) case FDDEFPRM32: case FDGETPRM32: { + compat_uptr_t name; struct floppy_struct32 *uf; struct floppy_struct *f; @@ -2130,7 +2131,8 @@ static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) err |= __get_user(f->rate, &uf->rate); err |= __get_user(f->spec1, &uf->spec1); err |= __get_user(f->fmt_gap, &uf->fmt_gap); - err |= __get_user((u64)f->name, &uf->name); + err |= __get_user(name, &uf->name); + f->name = compat_ptr(name); if (err) { err = -EFAULT; goto out; diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 5e48b9099cdb..6785c378d1be 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -1311,7 +1311,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry, memcpy (data1, de, len); de = (struct ext3_dir_entry_2 *) data1; top = data1 + len; - while (((char *) de2=(char*)de+le16_to_cpu(de->rec_len)) < top) + while ((char *)(de2=(void*)de+le16_to_cpu(de->rec_len)) < top) de = de2; de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de); /* Initialize the root; the dot dirents already exist */ diff --git a/fs/readdir.c b/fs/readdir.c index f9cd0419bf5e..3aff6efbf357 100644 --- a/fs/readdir.c +++ b/fs/readdir.c @@ -159,7 +159,7 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset, if (__put_user(0, dirent->d_name + namlen)) goto efault; buf->previous = dirent; - ((char *) dirent) += reclen; + dirent = (void *)dirent + reclen; buf->current_dir = dirent; buf->count -= reclen; return 0; @@ -245,7 +245,7 @@ static int filldir64(void * __buf, const char * name, int namlen, loff_t offset, if (__put_user(0, dirent->d_name + namlen)) goto efault; buf->previous = dirent; - ((char *) dirent) += reclen; + dirent = (void *)dirent + reclen; buf->current_dir = dirent; buf->count -= reclen; return 0; diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h index 42a1dcaf172b..d3054e6fa4bb 100644 --- a/include/asm-i386/apic.h +++ b/include/asm-i386/apic.h @@ -85,7 +85,7 @@ extern void disable_lapic_nmi_watchdog(void); extern void enable_lapic_nmi_watchdog(void); extern void disable_timer_nmi_watchdog(void); extern void enable_timer_nmi_watchdog(void); -extern inline void nmi_watchdog_tick (struct pt_regs * regs); +extern void nmi_watchdog_tick (struct pt_regs * regs); extern int APIC_init_uniprocessor (void); extern void disable_APIC_timer(void); extern void enable_APIC_timer(void); diff --git a/include/asm-i386/hw_irq.h b/include/asm-i386/hw_irq.h index 9b3b8bf9e266..b8166a30fbe1 100644 --- a/include/asm-i386/hw_irq.h +++ b/include/asm-i386/hw_irq.h @@ -26,7 +26,7 @@ */ extern u8 irq_vector[NR_IRQ_VECTORS]; -#define IO_APIC_VECTOR(irq) ((int)irq_vector[irq]) +#define IO_APIC_VECTOR(irq) (irq_vector[irq]) extern void (*interrupt[NR_IRQS])(void); diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h index 3adc789060f0..df3c08986b2d 100644 --- a/include/asm-i386/unistd.h +++ b/include/asm-i386/unistd.h @@ -394,7 +394,7 @@ static inline _syscall1(int,dup,int,fd) static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp) static inline _syscall3(int,open,const char *,file,int,flag,int,mode) static inline _syscall1(int,close,int,fd) -static inline _syscall1(int,_exit,int,exitcode) +static inline _syscall1(void,_exit,int,exitcode) static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options) #endif diff --git a/include/linux/efi.h b/include/linux/efi.h index a1764b1fb106..b29c8d42178f 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -297,8 +297,8 @@ extern u64 efi_mem_attributes (unsigned long phys_addr); extern void efi_initialize_iomem_resources(struct resource *code_resource, struct resource *data_resource); extern efi_status_t phys_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc); -extern inline unsigned long __init efi_get_time(void); -extern inline int __init efi_set_rtc_mmss(unsigned long nowtime); +extern unsigned long __init efi_get_time(void); +extern int __init efi_set_rtc_mmss(unsigned long nowtime); extern struct efi_memory_map memmap; /* diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index 32fe6c84b3b6..3e6c91301407 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -1781,25 +1781,25 @@ int reiserfs_convert_objectid_map_v1(struct super_block *) ; /* stree.c */ int B_IS_IN_TREE(const struct buffer_head *); extern inline void copy_short_key (void * to, const void * from); -extern inline void copy_item_head(struct item_head * p_v_to, +extern void copy_item_head(struct item_head * p_v_to, const struct item_head * p_v_from); // first key is in cpu form, second - le -extern inline int comp_keys (const struct key * le_key, +extern int comp_keys (const struct key * le_key, const struct cpu_key * cpu_key); -extern inline int comp_short_keys (const struct key * le_key, +extern int comp_short_keys (const struct key * le_key, const struct cpu_key * cpu_key); -extern inline void le_key2cpu_key (struct cpu_key * to, const struct key * from); +extern void le_key2cpu_key (struct cpu_key * to, const struct key * from); // both are cpu keys -extern inline int comp_cpu_keys (const struct cpu_key *, const struct cpu_key *); -extern inline int comp_short_cpu_keys (const struct cpu_key *, +extern int comp_cpu_keys (const struct cpu_key *, const struct cpu_key *); +extern int comp_short_cpu_keys (const struct cpu_key *, const struct cpu_key *); -extern inline void cpu_key2cpu_key (struct cpu_key *, const struct cpu_key *); +extern void cpu_key2cpu_key (struct cpu_key *, const struct cpu_key *); // both are in le form -extern inline int comp_le_keys (const struct key *, const struct key *); -extern inline int comp_short_le_keys (const struct key *, const struct key *); +extern int comp_le_keys (const struct key *, const struct key *); +extern int comp_short_le_keys (const struct key *, const struct key *); // // get key version from on disk key - kludge diff --git a/include/linux/sched.h b/include/linux/sched.h index f5f84aedbaec..e77f1330d90b 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -670,7 +670,7 @@ static inline int capable(int cap) extern struct mm_struct * mm_alloc(void); /* mmdrop drops the mm and the page tables */ -extern inline void FASTCALL(__mmdrop(struct mm_struct *)); +extern void FASTCALL(__mmdrop(struct mm_struct *)); static inline void mmdrop(struct mm_struct * mm) { if (atomic_dec_and_test(&mm->mm_count)) diff --git a/kernel/fork.c b/kernel/fork.c index b703d95dadc7..8d84f4e85766 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -416,7 +416,7 @@ struct mm_struct * mm_alloc(void) * is dropped: either by a lazy thread or by * mmput. Free the page directory and the mm. */ -inline void __mmdrop(struct mm_struct *mm) +void __mmdrop(struct mm_struct *mm) { BUG_ON(mm == &init_mm); mm_free_pgd(mm); diff --git a/lib/crc32.c b/lib/crc32.c index 86d8670569a7..2783fa38af65 100644 --- a/lib/crc32.c +++ b/lib/crc32.c @@ -99,7 +99,9 @@ u32 attribute((pure)) crc32_le(u32 crc, unsigned char const *p, size_t len) /* Align it */ if(unlikely(((long)b)&3 && len)){ do { - DO_CRC(*((u8 *)b)++); + u8 *p = (u8 *)b; + DO_CRC(*p++); + b = (void *)p; } while ((--len) && ((long)b)&3 ); } if(likely(len >= 4)){ @@ -120,7 +122,9 @@ u32 attribute((pure)) crc32_le(u32 crc, unsigned char const *p, size_t len) /* And the last few bytes */ if(len){ do { - DO_CRC(*((u8 *)b)++); + u8 *p = (u8 *)b; + DO_CRC(*p++); + b = (void *)p; } while (--len); } @@ -200,7 +204,9 @@ u32 attribute((pure)) crc32_be(u32 crc, unsigned char const *p, size_t len) /* Align it */ if(unlikely(((long)b)&3 && len)){ do { - DO_CRC(*((u8 *)b)++); + u8 *p = (u8 *)b; + DO_CRC(*p++); + b = (u32 *)p; } while ((--len) && ((long)b)&3 ); } if(likely(len >= 4)){ @@ -221,7 +227,9 @@ u32 attribute((pure)) crc32_be(u32 crc, unsigned char const *p, size_t len) /* And the last few bytes */ if(len){ do { - DO_CRC(*((u8 *)b)++); + u8 *p = (u8 *)b; + DO_CRC(*p++); + b = (void *)p; } while (--len); } return __be32_to_cpu(crc); -- cgit v1.2.3 From 71deb478873e5ad6c196fd53b2ace226bf913b65 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:32:45 -0800 Subject: [PATCH] gcc-3.5: fix extern inline decls include/linux/bio.h:234: sorry, unimplemented: inlining failed in call to 'bio_phys_segments': function body not available --- include/linux/bio.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/bio.h b/include/linux/bio.h index d3b4e9ed4052..3931d924141d 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -231,13 +231,13 @@ extern void bio_put(struct bio *); extern void bio_endio(struct bio *, unsigned int, int); struct request_queue; -extern inline int bio_phys_segments(struct request_queue *, struct bio *); -extern inline int bio_hw_segments(struct request_queue *, struct bio *); +extern int bio_phys_segments(struct request_queue *, struct bio *); +extern int bio_hw_segments(struct request_queue *, struct bio *); -extern inline void __bio_clone(struct bio *, struct bio *); +extern void __bio_clone(struct bio *, struct bio *); extern struct bio *bio_clone(struct bio *, int); -extern inline void bio_init(struct bio *); +extern void bio_init(struct bio *); extern int bio_add_page(struct bio *, struct page *, unsigned int,unsigned int); extern int bio_get_nr_vecs(struct block_device *); -- cgit v1.2.3 From 151a29549113f7793261cfa0a2a371af529bdf58 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:33:30 -0800 Subject: [PATCH] gcc-3.5: reiserfs fixes include/linux/reiserfs_fs.h:1837: sorry, unimplemented: inlining failed in call to 'decrement_bcount': function body not available --- include/linux/reiserfs_fs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index 3e6c91301407..594f305e613a 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -1834,7 +1834,7 @@ int search_by_key (struct super_block *, const struct cpu_key *, int search_for_position_by_key (struct super_block * p_s_sb, const struct cpu_key * p_s_cpu_key, struct path * p_s_search_path); -extern inline void decrement_bcount (struct buffer_head * p_s_bh); +extern void decrement_bcount (struct buffer_head * p_s_bh); void decrement_counters_in_path (struct path * p_s_search_path); void pathrelse (struct path * p_s_search_path); int reiserfs_check_path(struct path *p) ; @@ -1916,7 +1916,7 @@ void sd_attrs_to_i_attrs( __u16 sd_attrs, struct inode *inode ); void i_attrs_to_sd_attrs( struct inode *inode, __u16 *sd_attrs ); /* namei.c */ -inline void set_de_name_and_namelen (struct reiserfs_dir_entry * de); +void set_de_name_and_namelen (struct reiserfs_dir_entry * de); int search_by_entry_key (struct super_block * sb, const struct cpu_key * key, struct path * path, struct reiserfs_dir_entry * de); @@ -2037,7 +2037,7 @@ int balance_internal (struct tree_balance * , int, int, struct item_head * , struct buffer_head **); /* do_balance.c */ -inline void do_balance_mark_leaf_dirty (struct tree_balance * tb, +void do_balance_mark_leaf_dirty (struct tree_balance * tb, struct buffer_head * bh, int flag); #define do_balance_mark_internal_dirty do_balance_mark_leaf_dirty #define do_balance_mark_sb_dirty do_balance_mark_leaf_dirty -- cgit v1.2.3 From f0c3fe1713f030c0d2a7dac956cc7218792ee3ac Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:33:39 -0800 Subject: [PATCH] gcc-3.5: ide.h fixes include/linux/ide.h:1424: sorry, unimplemented: inlining failed in call to 'SELECT_MASK': function body not available --- include/linux/ide.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/include/linux/ide.h b/include/linux/ide.h index ef73baf33fc8..2b7777338be0 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1416,12 +1416,12 @@ typedef struct pkt_task_s { void *special; } pkt_task_t; -extern inline u32 ide_read_24(ide_drive_t *); +extern u32 ide_read_24(ide_drive_t *); -extern inline void SELECT_DRIVE(ide_drive_t *); -extern inline void SELECT_INTERRUPT(ide_drive_t *); -extern inline void SELECT_MASK(ide_drive_t *, int); -extern inline void QUIRK_LIST(ide_drive_t *); +extern void SELECT_DRIVE(ide_drive_t *); +extern void SELECT_INTERRUPT(ide_drive_t *); +extern void SELECT_MASK(ide_drive_t *, int); +extern void QUIRK_LIST(ide_drive_t *); extern void ata_input_data(ide_drive_t *, void *, u32); extern void ata_output_data(ide_drive_t *, void *, u32); -- cgit v1.2.3 From 8159ad9b6b2d6713047abc4d6fae2a3183337b63 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:33:48 -0800 Subject: [PATCH] gcc-3.5: elevator.h fixes include/linux/elevator.h:106: sorry, unimplemented: inlining failed in call to 'elv_try_last_merge': function body not available --- include/linux/elevator.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/elevator.h b/include/linux/elevator.h index cbd038b665e8..ce58f47126c1 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -96,9 +96,9 @@ extern elevator_t iosched_as; extern int elevator_init(request_queue_t *, elevator_t *); extern void elevator_exit(request_queue_t *); -extern inline int elv_rq_merge_ok(struct request *, struct bio *); -extern inline int elv_try_merge(struct request *, struct bio *); -extern inline int elv_try_last_merge(request_queue_t *, struct bio *); +extern int elv_rq_merge_ok(struct request *, struct bio *); +extern int elv_try_merge(struct request *, struct bio *); +extern int elv_try_last_merge(request_queue_t *, struct bio *); /* * Return values from elevator merger -- cgit v1.2.3 From c0ece855ddf1b0d8775dcf1465cafcb723add6e1 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:33:57 -0800 Subject: [PATCH] gcc-3.5: keyboard.c fixes drivers/char/keyboard.c:205: warning: use of conditional expressions as lvalues is deprecated --- drivers/char/keyboard.c | 2 +- drivers/input/evdev.c | 2 +- include/linux/input.h | 21 +++++++++++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 05c133771931..dc03b1a99956 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -202,7 +202,7 @@ int setkeycode(unsigned int scancode, unsigned int keycode) return -EINVAL; oldkey = INPUT_KEYCODE(dev, scancode); - INPUT_KEYCODE(dev, scancode) = keycode; + SET_INPUT_KEYCODE(dev, scancode, oldkey); clear_bit(oldkey, dev->keybit); set_bit(keycode, dev->keybit); diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 8a165f585f0e..0e16eeeb9e55 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -232,7 +232,7 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, if (t < 0 || t > dev->keycodemax || !dev->keycodesize) return -EINVAL; if (get_user(v, ((int *) arg) + 1)) return -EFAULT; u = INPUT_KEYCODE(dev, t); - INPUT_KEYCODE(dev, t) = v; + SET_INPUT_KEYCODE(dev, t, v); for (i = 0; i < dev->keycodemax; i++) if (v == u) break; if (i == dev->keycodemax) clear_bit(u, dev->keybit); set_bit(v, dev->keybit); diff --git a/include/linux/input.h b/include/linux/input.h index 3beb4078a2da..59afa63abbb3 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -751,6 +751,27 @@ struct ff_effect { #define init_input_dev(dev) do { INIT_LIST_HEAD(&((dev)->h_list)); INIT_LIST_HEAD(&((dev)->node)); } while (0) +#define SET_INPUT_KEYCODE(dev, scancode, val) \ + do { \ + switch (dev->keycodesize) { \ + case 1: { \ + u8 *k = (u8 *)dev->keycode; \ + k[scancode] = val; \ + break; \ + } \ + case 2: { \ + u16 *k = (u16 *)dev->keycode; \ + k[scancode] = val; \ + break; \ + } \ + case 4: { \ + u32 *k = (u32 *)dev->keycode; \ + k[scancode] = val; \ + break; \ + } \ + } \ + } while (0) + struct input_dev { void *private; -- cgit v1.2.3 From b3f36a2ae5d7eed8646f724eea863217875251ff Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:34:15 -0800 Subject: [PATCH] Fix inlining failure (all GCCs) in parport From: Jan Hubicka GCC never inline extern inline function redefined by new body (because it is not clear what body one should choose) parport contains such duplicated functions for apparently no good reasons. Both copies differ slightly, not sure whether it is intentional or just garbage. --- drivers/parport/parport_pc.c | 91 +------------------------------------------- include/linux/parport_pc.h | 20 +++++----- 2 files changed, 12 insertions(+), 99 deletions(-) (limited to 'include/linux') diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index d77c10a21539..3c37cba3cf7b 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -270,95 +270,6 @@ static irqreturn_t parport_pc_interrupt(int irq, void *dev_id, struct pt_regs *r return IRQ_HANDLED; } -void parport_pc_write_data(struct parport *p, unsigned char d) -{ - outb (d, DATA (p)); -} - -unsigned char parport_pc_read_data(struct parport *p) -{ - return inb (DATA (p)); -} - -void parport_pc_write_control(struct parport *p, unsigned char d) -{ - const unsigned char wm = (PARPORT_CONTROL_STROBE | - PARPORT_CONTROL_AUTOFD | - PARPORT_CONTROL_INIT | - PARPORT_CONTROL_SELECT); - - /* Take this out when drivers have adapted to the newer interface. */ - if (d & 0x20) { - printk (KERN_DEBUG "%s (%s): use data_reverse for this!\n", - p->name, p->cad->name); - parport_pc_data_reverse (p); - } - - __parport_pc_frob_control (p, wm, d & wm); -} - -unsigned char parport_pc_read_control(struct parport *p) -{ - const unsigned char wm = (PARPORT_CONTROL_STROBE | - PARPORT_CONTROL_AUTOFD | - PARPORT_CONTROL_INIT | - PARPORT_CONTROL_SELECT); - const struct parport_pc_private *priv = p->physport->private_data; - return priv->ctr & wm; /* Use soft copy */ -} - -unsigned char parport_pc_frob_control (struct parport *p, unsigned char mask, - unsigned char val) -{ - const unsigned char wm = (PARPORT_CONTROL_STROBE | - PARPORT_CONTROL_AUTOFD | - PARPORT_CONTROL_INIT | - PARPORT_CONTROL_SELECT); - - /* Take this out when drivers have adapted to the newer interface. */ - if (mask & 0x20) { - printk (KERN_DEBUG "%s (%s): use data_%s for this!\n", - p->name, p->cad->name, - (val & 0x20) ? "reverse" : "forward"); - if (val & 0x20) - parport_pc_data_reverse (p); - else - parport_pc_data_forward (p); - } - - /* Restrict mask and val to control lines. */ - mask &= wm; - val &= wm; - - return __parport_pc_frob_control (p, mask, val); -} - -unsigned char parport_pc_read_status(struct parport *p) -{ - return inb (STATUS (p)); -} - -void parport_pc_disable_irq(struct parport *p) -{ - __parport_pc_frob_control (p, 0x10, 0); -} - -void parport_pc_enable_irq(struct parport *p) -{ - if (p->irq != PARPORT_IRQ_NONE) - __parport_pc_frob_control (p, 0x10, 0x10); -} - -void parport_pc_data_forward (struct parport *p) -{ - __parport_pc_frob_control (p, 0x20, 0); -} - -void parport_pc_data_reverse (struct parport *p) -{ - __parport_pc_frob_control (p, 0x20, 0x20); -} - void parport_pc_init_state(struct pardevice *dev, struct parport_state *s) { s->u.pc.ctr = 0xc; @@ -1235,6 +1146,8 @@ dump_parport_state ("fwd idle", port); * ****************************************** */ +/* GCC is not inlining extern inline function later overwriten to non-inline, + so we use outlined_ variants here. */ struct parport_operations parport_pc_ops = { .write_data = parport_pc_write_data, diff --git a/include/linux/parport_pc.h b/include/linux/parport_pc.h index 47f14868ca75..2334281e3af6 100644 --- a/include/linux/parport_pc.h +++ b/include/linux/parport_pc.h @@ -41,7 +41,7 @@ struct parport_pc_private { struct pci_dev *dev; }; -extern __inline__ void parport_pc_write_data(struct parport *p, unsigned char d) +static __inline__ void parport_pc_write_data(struct parport *p, unsigned char d) { #ifdef DEBUG_PARPORT printk (KERN_DEBUG "parport_pc_write_data(%p,0x%02x)\n", p, d); @@ -49,7 +49,7 @@ extern __inline__ void parport_pc_write_data(struct parport *p, unsigned char d) outb(d, DATA(p)); } -extern __inline__ unsigned char parport_pc_read_data(struct parport *p) +static __inline__ unsigned char parport_pc_read_data(struct parport *p) { unsigned char val = inb (DATA (p)); #ifdef DEBUG_PARPORT @@ -124,17 +124,17 @@ static __inline__ unsigned char __parport_pc_frob_control (struct parport *p, return ctr; } -extern __inline__ void parport_pc_data_reverse (struct parport *p) +static __inline__ void parport_pc_data_reverse (struct parport *p) { __parport_pc_frob_control (p, 0x20, 0x20); } -extern __inline__ void parport_pc_data_forward (struct parport *p) +static __inline__ void parport_pc_data_forward (struct parport *p) { __parport_pc_frob_control (p, 0x20, 0x00); } -extern __inline__ void parport_pc_write_control (struct parport *p, +static __inline__ void parport_pc_write_control (struct parport *p, unsigned char d) { const unsigned char wm = (PARPORT_CONTROL_STROBE | @@ -152,7 +152,7 @@ extern __inline__ void parport_pc_write_control (struct parport *p, __parport_pc_frob_control (p, wm, d & wm); } -extern __inline__ unsigned char parport_pc_read_control(struct parport *p) +static __inline__ unsigned char parport_pc_read_control(struct parport *p) { const unsigned char rm = (PARPORT_CONTROL_STROBE | PARPORT_CONTROL_AUTOFD | @@ -162,7 +162,7 @@ extern __inline__ unsigned char parport_pc_read_control(struct parport *p) return priv->ctr & rm; /* Use soft copy */ } -extern __inline__ unsigned char parport_pc_frob_control (struct parport *p, +static __inline__ unsigned char parport_pc_frob_control (struct parport *p, unsigned char mask, unsigned char val) { @@ -189,18 +189,18 @@ extern __inline__ unsigned char parport_pc_frob_control (struct parport *p, return __parport_pc_frob_control (p, mask, val); } -extern __inline__ unsigned char parport_pc_read_status(struct parport *p) +static __inline__ unsigned char parport_pc_read_status(struct parport *p) { return inb(STATUS(p)); } -extern __inline__ void parport_pc_disable_irq(struct parport *p) +static __inline__ void parport_pc_disable_irq(struct parport *p) { __parport_pc_frob_control (p, 0x10, 0x00); } -extern __inline__ void parport_pc_enable_irq(struct parport *p) +static __inline__ void parport_pc_enable_irq(struct parport *p) { __parport_pc_frob_control (p, 0x10, 0x10); } -- cgit v1.2.3 From 6abf6a9ad145872e639149cdee9051a469621329 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:35:09 -0800 Subject: [PATCH] gcc-3.5: fsfilter.h, ntfs.h From: Tim Cambrant Fix inline decls in fsfilter.h, ntfs.h --- fs/ntfs/ntfs.h | 2 +- include/linux/fsfilter.h | 32 ++++++++++++++++---------------- 2 files changed, 17 insertions(+), 17 deletions(-) (limited to 'include/linux') diff --git a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h index fb28bde1ec9c..a2e8385b62cd 100644 --- a/fs/ntfs/ntfs.h +++ b/fs/ntfs/ntfs.h @@ -183,7 +183,7 @@ extern void post_write_mst_fixup(NTFS_RECORD *b); /* From fs/ntfs/time.c */ extern inline s64 utc2ntfs(const time_t time); extern inline s64 get_current_ntfs_time(void); -extern inline time_t ntfs2utc(const s64 time); +extern time_t ntfs2utc(const s64 time); /* From fs/ntfs/unistr.c */ extern BOOL ntfs_are_names_equal(const uchar_t *s1, size_t s1_len, diff --git a/include/linux/fsfilter.h b/include/linux/fsfilter.h index f425566a9299..0cd46770a844 100644 --- a/include/linux/fsfilter.h +++ b/include/linux/fsfilter.h @@ -74,22 +74,22 @@ extern struct filter_fs filter_oppar[FILTER_FS_TYPES]; struct filter_fs *filter_get_filter_fs(const char *cache_type); void filter_setup_journal_ops(struct filter_fs *ops, char *cache_type); -inline struct super_operations *filter_c2usops(struct filter_fs *cache); -inline struct inode_operations *filter_c2ufiops(struct filter_fs *cache); -inline struct inode_operations *filter_c2udiops(struct filter_fs *cache); -inline struct inode_operations *filter_c2usiops(struct filter_fs *cache); -inline struct file_operations *filter_c2uffops(struct filter_fs *cache); -inline struct file_operations *filter_c2udfops(struct filter_fs *cache); -inline struct file_operations *filter_c2usfops(struct filter_fs *cache); -inline struct super_operations *filter_c2csops(struct filter_fs *cache); -inline struct inode_operations *filter_c2cfiops(struct filter_fs *cache); -inline struct inode_operations *filter_c2cdiops(struct filter_fs *cache); -inline struct inode_operations *filter_c2csiops(struct filter_fs *cache); -inline struct file_operations *filter_c2cffops(struct filter_fs *cache); -inline struct file_operations *filter_c2cdfops(struct filter_fs *cache); -inline struct file_operations *filter_c2csfops(struct filter_fs *cache); -inline struct dentry_operations *filter_c2cdops(struct filter_fs *cache); -inline struct dentry_operations *filter_c2udops(struct filter_fs *cache); +struct super_operations *filter_c2usops(struct filter_fs *cache); +struct inode_operations *filter_c2ufiops(struct filter_fs *cache); +struct inode_operations *filter_c2udiops(struct filter_fs *cache); +struct inode_operations *filter_c2usiops(struct filter_fs *cache); +struct file_operations *filter_c2uffops(struct filter_fs *cache); +struct file_operations *filter_c2udfops(struct filter_fs *cache); +struct file_operations *filter_c2usfops(struct filter_fs *cache); +struct super_operations *filter_c2csops(struct filter_fs *cache); +struct inode_operations *filter_c2cfiops(struct filter_fs *cache); +struct inode_operations *filter_c2cdiops(struct filter_fs *cache); +struct inode_operations *filter_c2csiops(struct filter_fs *cache); +struct file_operations *filter_c2cffops(struct filter_fs *cache); +struct file_operations *filter_c2cdfops(struct filter_fs *cache); +struct file_operations *filter_c2csfops(struct filter_fs *cache); +struct dentry_operations *filter_c2cdops(struct filter_fs *cache); +struct dentry_operations *filter_c2udops(struct filter_fs *cache); void filter_setup_super_ops(struct filter_fs *cache, struct super_operations *cache_ops, struct super_operations *filter_sops); void filter_setup_dir_ops(struct filter_fs *cache, struct inode *cache_inode, struct inode_operations *filter_iops, struct file_operations *ffops); -- cgit v1.2.3 From 7767803d4a857fa405401074aa49592943fd1dbe Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:39:47 -0800 Subject: [PATCH] gcc-3.5: arch/i386/kernel/traps.c ++nmi_count(cpu); arch/i386/kernel/traps.c: In function `do_nmi': arch/i386/kernel/traps.c:552: error: invalid lvalue in increment and include/linux/netdevice.h: In function `__netif_rx_schedule': include/linux/netdevice.h:818: error: invalid lvalue in assignment include/linux/netdevice.h: In function `netif_rx_reschedule': include/linux/netdevice.h:842: error: invalid lvalue in assignment This fix will probably reintroduce unused variable warnings... --- include/linux/irq_cpustat.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/irq_cpustat.h b/include/linux/irq_cpustat.h index 03b3e17de805..95e55a9f1087 100644 --- a/include/linux/irq_cpustat.h +++ b/include/linux/irq_cpustat.h @@ -19,11 +19,7 @@ #ifndef __ARCH_IRQ_STAT extern irq_cpustat_t irq_stat[]; /* defined in asm/hardirq.h */ -#ifdef CONFIG_SMP #define __IRQ_STAT(cpu, member) (irq_stat[cpu].member) -#else -#define __IRQ_STAT(cpu, member) ((void)(cpu), irq_stat[0].member) -#endif #endif /* arch independent irq_stat fields */ -- cgit v1.2.3 From 29d82b14a433fcba36b7cc062271225976355eaf Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:40:05 -0800 Subject: [PATCH] bitmap parsing/printing routines, version 4 From: Joe Korty 1) the version in 2.6.1 is broken, doesn't work on 64bit big endian machines at all. This needed fixing. I thought it best to fix by rewriting the printer/parser with an algorithm that is naturally endian & sizeof(long) resistant. 2) I wanted all digits to print, eg, 0000ffff,00000004 not ffff,4. 3) I wanted exactly NR_CPUS bits to print (or whatever the bitmap size is in bits, and not have what is displayed rounded up to the nearest full byte, as the current version did. 4) The bitmap printer and parser should be part of bitmap.[ch] with syntax and semantics to match. The original lib/mask.c versions did not recognize this commonality. --- include/linux/bitmap.h | 4 ++ include/linux/cpumask.h | 11 +-- lib/Makefile | 2 +- lib/bitmap.c | 149 +++++++++++++++++++++++++++++++++++++++- lib/mask.c | 178 ------------------------------------------------ 5 files changed, 154 insertions(+), 190 deletions(-) delete mode 100644 lib/mask.c (limited to 'include/linux') diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h index b84caaebed87..97fec37b1029 100644 --- a/include/linux/bitmap.h +++ b/include/linux/bitmap.h @@ -41,6 +41,10 @@ void bitmap_and(unsigned long *dst, const unsigned long *bitmap1, void bitmap_or(unsigned long *dst, const unsigned long *bitmap1, const unsigned long *bitmap2, int bits); int bitmap_weight(const unsigned long *bitmap, int bits); +int bitmap_snprintf(char *buf, unsigned int buflen, + const unsigned long *maskp, int bits); +int bitmap_parse(const char __user *ubuf, unsigned int ubuflen, + unsigned long *maskp, int bits); #endif /* __ASSEMBLY__ */ diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index 6fa750a5b26e..f19587e5c71a 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -2,6 +2,7 @@ #define __LINUX_CPUMASK_H #include +#include #include #include @@ -31,16 +32,10 @@ extern cpumask_t cpu_possible_map; #define for_each_online_cpu(cpu) for (cpu = 0; cpu < 1; cpu++) #endif -extern int __mask_snprintf_len(char *buf, unsigned int buflen, - const unsigned long *maskp, unsigned int maskbytes); - #define cpumask_snprintf(buf, buflen, map) \ - __mask_snprintf_len(buf, buflen, cpus_addr(map), sizeof(map)) - -extern int __mask_parse_len(const char __user *ubuf, unsigned int ubuflen, - unsigned long *maskp, unsigned int maskbytes); + bitmap_snprintf(buf, buflen, cpus_addr(map), NR_CPUS) #define cpumask_parse(buf, buflen, map) \ - __mask_parse_len(buf, buflen, cpus_addr(map), sizeof(map)) + bitmap_parse(buf, buflen, cpus_addr(map), NR_CPUS) #endif /* __LINUX_CPUMASK_H */ diff --git a/lib/Makefile b/lib/Makefile index 3f1c4af35166..c489f79b9dfa 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -5,7 +5,7 @@ lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \ bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \ - kobject.o idr.o div64.o parser.o int_sqrt.o mask.o \ + kobject.o idr.o div64.o parser.o int_sqrt.o \ bitmap.o extable.o lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o diff --git a/lib/bitmap.c b/lib/bitmap.c index 6462e071167b..fb09dffaa557 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c @@ -1,5 +1,18 @@ -#include +/* + * lib/bitmap.c + * Helper functions for bitmap.h. + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ #include +#include +#include +#include +#include +#include + +#define MAX_BITMAP_BITS 512U /* for ia64 NR_CPUS maximum */ int bitmap_empty(const unsigned long *bitmap, int bits) { @@ -62,8 +75,9 @@ void bitmap_shift_right(unsigned long *dst, const unsigned long *src, int shift, int bits) { int k; - DECLARE_BITMAP(__shr_tmp, bits); + DECLARE_BITMAP(__shr_tmp, MAX_BITMAP_BITS); + BUG_ON(bits > MAX_BITMAP_BITS); bitmap_clear(__shr_tmp, bits); for (k = 0; k < bits - shift; ++k) if (test_bit(k + shift, src)) @@ -76,8 +90,9 @@ void bitmap_shift_left(unsigned long *dst, const unsigned long *src, int shift, int bits) { int k; - DECLARE_BITMAP(__shl_tmp, bits); + DECLARE_BITMAP(__shl_tmp, MAX_BITMAP_BITS); + BUG_ON(bits > MAX_BITMAP_BITS); bitmap_clear(__shl_tmp, bits); for (k = bits; k >= shift; --k) if (test_bit(k - shift, src)) @@ -139,3 +154,131 @@ int bitmap_weight(const unsigned long *bitmap, int bits) #endif EXPORT_SYMBOL(bitmap_weight); +/* + * Bitmap printing & parsing functions: first version by Bill Irwin, + * second version by Paul Jackson, third by Joe Korty. + */ + +#define CHUNKSZ 32 +#define nbits_to_hold_value(val) fls(val) +#define roundup_power2(val,modulus) (((val) + (modulus) - 1) & ~((modulus) - 1)) +#define unhex(c) (isdigit(c) ? (c - '0') : (toupper(c) - 'A' + 10)) + +/** + * bitmap_snprintf - convert bitmap to an ASCII hex string. + * @buf: byte buffer into which string is placed + * @buflen: reserved size of @buf, in bytes + * @maskp: pointer to bitmap to convert + * @nmaskbits: size of bitmap, in bits + * + * Exactly @nmaskbits bits are displayed. Hex digits are grouped into + * comma-separated sets of eight digits per set. + */ +int bitmap_snprintf(char *buf, unsigned int buflen, + const unsigned long *maskp, int nmaskbits) +{ + int i, word, bit, len = 0; + unsigned long val; + const char *sep = ""; + int chunksz; + u32 chunkmask; + + chunksz = nmaskbits & (CHUNKSZ - 1); + if (chunksz == 0) + chunksz = CHUNKSZ; + + i = roundup_power2(nmaskbits, CHUNKSZ) - CHUNKSZ; + for (; i >= 0; i -= CHUNKSZ) { + chunkmask = ((1ULL << chunksz) - 1); + word = i / BITS_PER_LONG; + bit = i % BITS_PER_LONG; + val = (maskp[word] >> bit) & chunkmask; + len += snprintf(buf+len, buflen-len, "%s%0*lx", sep, + (chunksz+3)/4, val); + chunksz = CHUNKSZ; + sep = ","; + } + return len; +} +EXPORT_SYMBOL(bitmap_snprintf); + +/** + * bitmap_parse - convert an ASCII hex string into a bitmap. + * @buf: pointer to buffer in user space containing string. + * @buflen: buffer size in bytes. If string is smaller than this + * then it must be terminated with a \0. + * @maskp: pointer to bitmap array that will contain result. + * @nmaskbits: size of bitmap, in bits. + * + * Commas group hex digits into chunks. Each chunk defines exactly 32 + * bits of the resultant bitmask. No chunk may specify a value larger + * than 32 bits (-EOVERFLOW), and if a chunk specifies a smaller value + * then leading 0-bits are prepended. -EINVAL is returned for illegal + * characters and for grouping errors such as "1,,5", ",44", "," and "". + * Leading and trailing whitespace accepted, but not embedded whitespace. + */ +int bitmap_parse(const char __user *ubuf, unsigned int ubuflen, + unsigned long *maskp, int nmaskbits) +{ + int i, c, old_c, totaldigits, ndigits, nchunks, nbits; + u32 chunk; + + bitmap_clear(maskp, nmaskbits); + + nchunks = nbits = totaldigits = c = 0; + do { + chunk = ndigits = 0; + + /* Get the next chunk of the bitmap */ + while (ubuflen) { + old_c = c; + if (get_user(c, ubuf++)) + return -EFAULT; + ubuflen--; + if (isspace(c)) + continue; + + /* + * If the last character was a space and the current + * character isn't '\0', we've got embedded whitespace. + * This is a no-no, so throw an error. + */ + if (totaldigits && c && isspace(old_c)) + return -EINVAL; + + /* A '\0' or a ',' signal the end of the chunk */ + if (c == '\0' || c == ',') + break; + + if (!isxdigit(c)) + return -EINVAL; + + /* + * Make sure there are at least 4 free bits in 'chunk'. + * If not, this hexdigit will overflow 'chunk', so + * throw an error. + */ + if (chunk & ~((1UL << (CHUNKSZ - 4)) - 1)) + return -EOVERFLOW; + + chunk = (chunk << 4) | unhex(c); + ndigits++; totaldigits++; + } + if (ndigits == 0) + return -EINVAL; + if (nchunks == 0 && chunk == 0) + continue; + + bitmap_shift_right(maskp, maskp, CHUNKSZ, nmaskbits); + for (i = 0; i < CHUNKSZ; i++) + if (chunk & (1 << i)) + set_bit(i, maskp); + nchunks++; + nbits += (nchunks == 1) ? nbits_to_hold_value(chunk) : CHUNKSZ; + if (nbits > nmaskbits) + return -EOVERFLOW; + } while (ubuflen && c == ','); + + return 0; +} +EXPORT_SYMBOL(bitmap_parse); diff --git a/lib/mask.c b/lib/mask.c deleted file mode 100644 index 231cb05cc1a0..000000000000 --- a/lib/mask.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * lib/mask.c - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2003 Silicon Graphics, Inc. All Rights Reserved. - */ - -/* - * Routines to manipulate multi-word bit masks, such as cpumasks. - * - * The ascii representation of multi-word bit masks displays each - * 32bit word in hex (not zero filled), and for masks longer than - * one word, uses a comma separator between words. Words are - * displayed in big-endian order most significant first. And hex - * digits within a word are also in big-endian order, of course. - * - * Examples: - * A mask with just bit 0 set displays as "1". - * A mask with just bit 127 set displays as "80000000,0,0,0". - * A mask with just bit 64 set displays as "1,0,0". - * A mask with bits 0, 1, 2, 4, 8, 16, 32 and 64 set displays - * as "1,1,10117". The first "1" is for bit 64, the second - * for bit 32, the third for bit 16, and so forth, to the - * "7", which is for bits 2, 1 and 0. - * A mask with bits 32 through 39 set displays as "ff,0". - * - * The internal binary representation of masks is as one or - * an array of unsigned longs, perhaps wrapped in a struct for - * convenient use as an lvalue. The following code doesn't know - * about any such struct details, relying on inline macros in - * files such as cpumask.h to pass in an unsigned long pointer - * and a length (in bytes), describing the mask contents. - * The 32bit words in the array are in little-endian order, - * low order word first. Beware that this is the reverse order - * of the ascii representation. - * - * Even though the size of the input mask is provided in bytes, - * the following code may assume that the mask is a multiple of - * 32 or 64 bit words long, and ignore any fractional portion - * of a word at the end. The main reason the size is passed in - * bytes is because it is so easy to write 'sizeof(somemask_t)' - * in the macros. - * - * Masks are not a single,simple type, like classic 'C' - * nul-term strings. Rather they are a family of types, one - * for each different length. Inline macros are used to pick - * up the actual length, where it is known to the compiler, and - * pass it down to these routines, which work on any specified - * length array of unsigned longs. Poor man's templates. - * - * Many of the inline macros don't call into the following - * routines. Some of them call into other kernel routines, - * such as memset(), set_bit() or ffs(). Some of them can - * accomplish their task right inline, such as returning the - * size or address of the unsigned long array, or optimized - * versions of the macros for the most common case of an array - * of a single unsigned long. - */ - -#include -#include -#include -#include -#include -#include -#include - -#define MAX_HEX_PER_BYTE 4 /* dont need > 4 hex chars to encode byte */ -#define BASE 16 /* masks are input in hex (base 16) */ -#define NUL ((char)'\0') /* nul-terminator */ - -/** - * __mask_snprintf_len - represent multi-word bit mask as string. - * @buf: The buffer to place the result into - * @buflen: The size of the buffer, including the trailing null space - * @maskp: Points to beginning of multi-word bit mask. - * @maskbytes: Number of bytes in bit mask at maskp. - * - * This routine is expected to be called from a macro such as: - * - * #define cpumask_snprintf(buf, buflen, mask) \ - * __mask_snprintf_len(buf, buflen, cpus_addr(mask), sizeof(mask)) - */ - -int __mask_snprintf_len(char *buf, unsigned int buflen, - const unsigned long *maskp, unsigned int maskbytes) -{ - u32 *wordp = (u32 *)maskp; - int i = maskbytes/sizeof(u32) - 1; - int len = 0; - char *sep = ""; - - while (i >= 1 && wordp[i] == 0) - i--; - while (i >= 0) { - len += snprintf(buf+len, buflen-len, "%s%x", sep, wordp[i]); - sep = ","; - i--; - } - return len; -} - -/** - * __mask_parse_len - parse user string into maskbytes mask at maskp - * @ubuf: The user buffer from which to take the string - * @ubuflen: The size of this buffer, including the terminating char - * @maskp: Place resulting mask (array of unsigned longs) here - * @masklen: Construct mask at @maskp to have exactly @masklen bytes - * - * @masklen is a multiple of sizeof(unsigned long). A mask of - * @masklen bytes is constructed starting at location @maskp. - * The value of this mask is specified by the user provided - * string starting at address @ubuf. Only bytes in the range - * [@ubuf, @ubuf+@ubuflen) can be read from user space, and - * reading will stop after the first byte that is not a comma - * or valid hex digit in the characters [,0-9a-fA-F], or at - * the point @ubuf+@ubuflen, whichever comes first. - * - * Since the user only needs about 2.25 chars per byte to encode - * a mask (one char per nibble plus one comma separator or nul - * terminator per byte), we blow them off with -EINVAL if they - * claim a @ubuflen more than 4 (MAX_HEX_PER_BYTE) times maskbytes. - * An empty word (delimited by two consecutive commas, for example) - * is taken as zero. If @buflen is zero, the entire @maskp is set - * to zero. - * - * If the user provides fewer comma-separated ascii words - * than there are 32 bit words in maskbytes, we zero fill the - * remaining high order words. If they provide more, they fail - * with -EINVAL. Each comma-separate ascii word is taken as - * a hex representation; leading zeros are ignored, and do not - * imply octal. '00e1', 'e1', '00E1', 'E1' are all the same. - * If user passes a word that is larger than fits in a u32, - * they fail with -EOVERFLOW. - */ - -int __mask_parse_len(const char __user *ubuf, unsigned int ubuflen, - unsigned long *maskp, unsigned int maskbytes) -{ - char buf[maskbytes * MAX_HEX_PER_BYTE + sizeof(NUL)]; - char *bp = buf; - u32 *wordp = (u32 *)maskp; - char *p; - int i, j; - - if (ubuflen > maskbytes * MAX_HEX_PER_BYTE) - return -EINVAL; - if (copy_from_user(buf, ubuf, ubuflen)) - return -EFAULT; - buf[ubuflen] = NUL; - - /* - * Put the words into wordp[] in big-endian order, - * then go back and reverse them. - */ - memset(wordp, 0, maskbytes); - i = j = 0; - while ((p = strsep(&bp, ",")) != NULL) { - unsigned long long t; - if (j == maskbytes/sizeof(u32)) - return -EINVAL; - t = simple_strtoull(p, 0, BASE); - if (t != (u32)t) - return -EOVERFLOW; - wordp[j++] = t; - } - --j; - while (i < j) { - u32 t = wordp[i]; - wordp[i] = wordp[j]; - wordp[j] = t; - i++, --j; - } - return 0; -} -- cgit v1.2.3 From e086c19275ab84257dc3df71fb071d9be0e6b2ec Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:41:01 -0800 Subject: [PATCH] use __attribute_const__ everywhere From: Nikita Danilov Replace all existing usages of __attribute__((const)) with __attribute_const__. --- arch/ia64/kernel/unwind.c | 2 +- drivers/usb/class/audio.c | 4 ++-- include/asm-alpha/byteorder.h | 2 +- include/asm-arm/current.h | 2 +- include/asm-arm/thread_info.h | 2 +- include/asm-arm26/current.h | 2 +- include/asm-arm26/thread_info.h | 2 +- include/asm-m68k/virtconvert.h | 4 ++-- include/asm-ppc/io.h | 2 +- include/asm-ppc/pgtable.h | 2 +- include/asm-sparc/btfixup.h | 14 +++++++------- include/asm-sparc/pgtable.h | 20 ++++++++++---------- include/linux/reiserfs_fs.h | 2 +- 13 files changed, 30 insertions(+), 30 deletions(-) (limited to 'include/linux') diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c index a2f7322cd76b..9eb9074452fa 100644 --- a/arch/ia64/kernel/unwind.c +++ b/arch/ia64/kernel/unwind.c @@ -650,7 +650,7 @@ free_state_stack (struct unw_reg_state *rs) /* Unwind decoder routines */ -static enum unw_register_index __attribute__((const)) +static enum unw_register_index __attribute_const__ decode_abreg (unsigned char abreg, int memory) { switch (abreg) { diff --git a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c index 618c42d4cb28..37f6070e6936 100644 --- a/drivers/usb/class/audio.c +++ b/drivers/usb/class/audio.c @@ -203,12 +203,12 @@ #define AUDIO_DEBUG 1 -#define SND_DEV_DSP16 5 +#define SND_DEV_DSP16 5 #define dprintk(x) #undef abs -extern int abs(int __x) __attribute__ ((__const__)); /* Shut up warning */ +extern int abs(int __x) __attribute_const__; /* Shut up warning */ /* --------------------------------------------------------------------- */ diff --git a/include/asm-alpha/byteorder.h b/include/asm-alpha/byteorder.h index ddf4e740e72a..e5179c55920c 100644 --- a/include/asm-alpha/byteorder.h +++ b/include/asm-alpha/byteorder.h @@ -6,7 +6,7 @@ #ifdef __GNUC__ -static __inline __u32 __attribute__((__const)) __arch__swab32(__u32 x) +static __inline __u32 __attribute_const__ __arch__swab32(__u32 x) { /* * Unfortunately, we can't use the 6 instruction sequence diff --git a/include/asm-arm/current.h b/include/asm-arm/current.h index b3d68cd03f73..75d21e2a3ff7 100644 --- a/include/asm-arm/current.h +++ b/include/asm-arm/current.h @@ -3,7 +3,7 @@ #include -static inline struct task_struct *get_current(void) __attribute__ (( __const__ )); +static inline struct task_struct *get_current(void) __attribute_const__; static inline struct task_struct *get_current(void) { diff --git a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h index 16a541206166..95e3c9c996d3 100644 --- a/include/asm-arm/thread_info.h +++ b/include/asm-arm/thread_info.h @@ -77,7 +77,7 @@ struct thread_info { /* * how to get the thread information struct from C */ -static inline struct thread_info *current_thread_info(void) __attribute__ (( __const__ )); +static inline struct thread_info *current_thread_info(void) __attribute_const__; static inline struct thread_info *current_thread_info(void) { diff --git a/include/asm-arm26/current.h b/include/asm-arm26/current.h index b3d68cd03f73..75d21e2a3ff7 100644 --- a/include/asm-arm26/current.h +++ b/include/asm-arm26/current.h @@ -3,7 +3,7 @@ #include -static inline struct task_struct *get_current(void) __attribute__ (( __const__ )); +static inline struct task_struct *get_current(void) __attribute_const__; static inline struct task_struct *get_current(void) { diff --git a/include/asm-arm26/thread_info.h b/include/asm-arm26/thread_info.h index 24c5136484fb..e57f9b2b17b7 100644 --- a/include/asm-arm26/thread_info.h +++ b/include/asm-arm26/thread_info.h @@ -71,7 +71,7 @@ struct thread_info { /* * how to get the thread information struct from C */ -static inline struct thread_info *current_thread_info(void) __attribute__ (( __const__ )); +static inline struct thread_info *current_thread_info(void) __attribute_const__; static inline struct thread_info *current_thread_info(void) { diff --git a/include/asm-m68k/virtconvert.h b/include/asm-m68k/virtconvert.h index 435fca52a91e..68205b61820c 100644 --- a/include/asm-m68k/virtconvert.h +++ b/include/asm-m68k/virtconvert.h @@ -19,8 +19,8 @@ * Change virtual addresses to physical addresses and vv. */ #ifndef CONFIG_SUN3 -extern unsigned long mm_vtop(unsigned long addr) __attribute__ ((const)); -extern unsigned long mm_ptov(unsigned long addr) __attribute__ ((const)); +extern unsigned long mm_vtop(unsigned long addr) __attribute_const__; +extern unsigned long mm_ptov(unsigned long addr) __attribute_const__; #else static inline unsigned long mm_vtop(unsigned long vaddr) { diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h index ca70e02cb0d9..0c78d0c505c7 100644 --- a/include/asm-ppc/io.h +++ b/include/asm-ppc/io.h @@ -211,7 +211,7 @@ extern void *ioremap64(unsigned long long address, unsigned long size); #define ioremap_nocache(addr, size) ioremap((addr), (size)) extern void iounmap(void *addr); extern unsigned long iopa(unsigned long addr); -extern unsigned long mm_ptov(unsigned long addr) __attribute__ ((const)); +extern unsigned long mm_ptov(unsigned long addr) __attribute_const__; extern void io_block_mapping(unsigned long virt, phys_addr_t phys, unsigned int size, int flags); diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h index 53fa036d620a..0cf6aab40dfb 100644 --- a/include/asm-ppc/pgtable.h +++ b/include/asm-ppc/pgtable.h @@ -626,7 +626,7 @@ extern void cache_clear(__u32 addr, int length); extern void cache_push(__u32 addr, int length); extern int mm_end_of_chunk (unsigned long addr, int len); extern unsigned long iopa(unsigned long addr); -extern unsigned long mm_ptov(unsigned long addr) __attribute__ ((const)); +extern unsigned long mm_ptov(unsigned long addr) __attribute_const__; /* Values for nocacheflag and cmode */ /* These are not used by the APUS kernel_map, but prevents diff --git a/include/asm-sparc/btfixup.h b/include/asm-sparc/btfixup.h index f0ea6d09d1de..b84c96c89581 100644 --- a/include/asm-sparc/btfixup.h +++ b/include/asm-sparc/btfixup.h @@ -39,7 +39,7 @@ extern unsigned int ___illegal_use_of_BTFIXUP_INT_in_module(void); extern __type ___f_##__name(__args); \ extern unsigned ___fs_##__name[3]; #define BTFIXUPDEF_CALL_CONST(__type, __name, __args...) \ - extern __type ___f_##__name(__args) __attribute__((const)); \ + extern __type ___f_##__name(__args) __attribute_const__; \ extern unsigned ___fs_##__name[3]; #define BTFIXUP_CALL(__name) ___f_##__name @@ -49,7 +49,7 @@ extern unsigned int ___illegal_use_of_BTFIXUP_INT_in_module(void); /* Put bottom 13bits into some register variable */ #define BTFIXUPDEF_SIMM13(__name) \ - extern unsigned int ___sf_##__name(void) __attribute__((const)); \ + extern unsigned int ___sf_##__name(void) __attribute_const__; \ extern unsigned ___ss_##__name[2]; \ extern __inline__ unsigned int ___sf_##__name(void) { \ unsigned int ret; \ @@ -57,7 +57,7 @@ extern unsigned int ___illegal_use_of_BTFIXUP_INT_in_module(void); return ret; \ } #define BTFIXUPDEF_SIMM13_INIT(__name,__val) \ - extern unsigned int ___sf_##__name(void) __attribute__((const)); \ + extern unsigned int ___sf_##__name(void) __attribute_const__; \ extern unsigned ___ss_##__name[2]; \ extern __inline__ unsigned int ___sf_##__name(void) { \ unsigned int ret; \ @@ -71,7 +71,7 @@ extern unsigned int ___illegal_use_of_BTFIXUP_INT_in_module(void); */ #define BTFIXUPDEF_HALF(__name) \ - extern unsigned int ___af_##__name(void) __attribute__((const)); \ + extern unsigned int ___af_##__name(void) __attribute_const__; \ extern unsigned ___as_##__name[2]; \ extern __inline__ unsigned int ___af_##__name(void) { \ unsigned int ret; \ @@ -79,7 +79,7 @@ extern unsigned int ___illegal_use_of_BTFIXUP_INT_in_module(void); return ret; \ } #define BTFIXUPDEF_HALF_INIT(__name,__val) \ - extern unsigned int ___af_##__name(void) __attribute__((const)); \ + extern unsigned int ___af_##__name(void) __attribute_const__; \ extern unsigned ___as_##__name[2]; \ extern __inline__ unsigned int ___af_##__name(void) { \ unsigned int ret; \ @@ -90,7 +90,7 @@ extern unsigned int ___illegal_use_of_BTFIXUP_INT_in_module(void); /* Put upper 22 bits into some register variable */ #define BTFIXUPDEF_SETHI(__name) \ - extern unsigned int ___hf_##__name(void) __attribute__((const)); \ + extern unsigned int ___hf_##__name(void) __attribute_const__; \ extern unsigned ___hs_##__name[2]; \ extern __inline__ unsigned int ___hf_##__name(void) { \ unsigned int ret; \ @@ -98,7 +98,7 @@ extern unsigned int ___illegal_use_of_BTFIXUP_INT_in_module(void); return ret; \ } #define BTFIXUPDEF_SETHI_INIT(__name,__val) \ - extern unsigned int ___hf_##__name(void) __attribute__((const)); \ + extern unsigned int ___hf_##__name(void) __attribute_const__; \ extern unsigned ___hs_##__name[2]; \ extern __inline__ unsigned int ___hf_##__name(void) { \ unsigned int ret; \ diff --git a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h index bba6e03c4cbb..b0baa22ffa48 100644 --- a/include/asm-sparc/pgtable.h +++ b/include/asm-sparc/pgtable.h @@ -80,7 +80,7 @@ BTFIXUPDEF_SIMM13(pmd_shift) BTFIXUPDEF_SETHI(pmd_size) BTFIXUPDEF_SETHI(pmd_mask) -extern unsigned int pmd_align(unsigned int addr) __attribute__((const)); +extern unsigned int pmd_align(unsigned int addr) __attribute_const__; extern __inline__ unsigned int pmd_align(unsigned int addr) { return ((addr + ~BTFIXUP_SETHI(pmd_mask)) & BTFIXUP_SETHI(pmd_mask)); @@ -90,7 +90,7 @@ BTFIXUPDEF_SIMM13(pgdir_shift) BTFIXUPDEF_SETHI(pgdir_size) BTFIXUPDEF_SETHI(pgdir_mask) -extern unsigned int pgdir_align(unsigned int addr) __attribute__((const)); +extern unsigned int pgdir_align(unsigned int addr) __attribute_const__; extern __inline__ unsigned int pgdir_align(unsigned int addr) { return ((addr + ~BTFIXUP_SETHI(pgdir_mask)) & BTFIXUP_SETHI(pgdir_mask)); @@ -248,19 +248,19 @@ BTFIXUPDEF_HALF(pte_writei) BTFIXUPDEF_HALF(pte_dirtyi) BTFIXUPDEF_HALF(pte_youngi) -extern int pte_write(pte_t pte) __attribute__((const)); +extern int pte_write(pte_t pte) __attribute_const__; extern __inline__ int pte_write(pte_t pte) { return pte_val(pte) & BTFIXUP_HALF(pte_writei); } -extern int pte_dirty(pte_t pte) __attribute__((const)); +extern int pte_dirty(pte_t pte) __attribute_const__; extern __inline__ int pte_dirty(pte_t pte) { return pte_val(pte) & BTFIXUP_HALF(pte_dirtyi); } -extern int pte_young(pte_t pte) __attribute__((const)); +extern int pte_young(pte_t pte) __attribute_const__; extern __inline__ int pte_young(pte_t pte) { return pte_val(pte) & BTFIXUP_HALF(pte_youngi); @@ -271,7 +271,7 @@ extern __inline__ int pte_young(pte_t pte) */ BTFIXUPDEF_HALF(pte_filei) -extern int pte_file(pte_t pte) __attribute__((const)); +extern int pte_file(pte_t pte) __attribute_const__; extern __inline__ int pte_file(pte_t pte) { return pte_val(pte) & BTFIXUP_HALF(pte_filei); @@ -283,19 +283,19 @@ BTFIXUPDEF_HALF(pte_wrprotecti) BTFIXUPDEF_HALF(pte_mkcleani) BTFIXUPDEF_HALF(pte_mkoldi) -extern pte_t pte_wrprotect(pte_t pte) __attribute__((const)); +extern pte_t pte_wrprotect(pte_t pte) __attribute_const__; extern __inline__ pte_t pte_wrprotect(pte_t pte) { return __pte(pte_val(pte) & ~BTFIXUP_HALF(pte_wrprotecti)); } -extern pte_t pte_mkclean(pte_t pte) __attribute__((const)); +extern pte_t pte_mkclean(pte_t pte) __attribute_const__; extern __inline__ pte_t pte_mkclean(pte_t pte) { return __pte(pte_val(pte) & ~BTFIXUP_HALF(pte_mkcleani)); } -extern pte_t pte_mkold(pte_t pte) __attribute__((const)); +extern pte_t pte_mkold(pte_t pte) __attribute_const__; extern __inline__ pte_t pte_mkold(pte_t pte) { return __pte(pte_val(pte) & ~BTFIXUP_HALF(pte_mkoldi)); @@ -332,7 +332,7 @@ BTFIXUPDEF_CALL_CONST(pte_t, mk_pte_io, unsigned long, pgprot_t, int) BTFIXUPDEF_INT(pte_modify_mask) -extern pte_t pte_modify(pte_t pte, pgprot_t newprot) __attribute__((const)); +extern pte_t pte_modify(pte_t pte, pgprot_t newprot) __attribute_const__; extern __inline__ pte_t pte_modify(pte_t pte, pgprot_t newprot) { return __pte((pte_val(pte) & BTFIXUP_INT(pte_modify_mask)) | diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index 594f305e613a..f05d63a025c4 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -90,7 +90,7 @@ if( !( cond ) ) \ #define RFALSE( cond, format, args... ) do {;} while( 0 ) #endif -#define CONSTF __attribute__( ( const ) ) +#define CONSTF __attribute_const__ /* * Disk Data Structures */ -- cgit v1.2.3 From 9db89cf785e61599a142c6db2f12cda75f35eb9d Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:41:31 -0800 Subject: [PATCH] Trivial cleanups for swsusp From: Pavel Machek This kills unused part of struct and fixes spelling. It also fixes codingstyle a bit, converts "can not happen" panic into BUG_ON (fill_suspend_header() allocates no memory so panic is meaningless) and adds check for sizeof (struct link) [if that is not PAGE_SIZE, we have *bad* problem, better check early]. --- include/linux/suspend.h | 3 --- kernel/power/swsusp.c | 19 ++++++++++--------- 2 files changed, 10 insertions(+), 12 deletions(-) (limited to 'include/linux') diff --git a/include/linux/suspend.h b/include/linux/suspend.h index db4d007f4a8b..cd90591947bc 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -32,9 +32,6 @@ struct suspend_header { int page_size; suspend_pagedir_t *suspend_pagedir; unsigned int num_pbes; - struct swap_location { - char filename[SWAP_FILENAME_MAXLENGTH]; - } swap_location[MAX_SWAPFILES]; }; #define SUSPEND_PD_PAGES(x) (((x)*sizeof(struct pbe))/PAGE_SIZE+1) diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index ffa284f71a4d..b233f924a3ba 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -284,8 +284,8 @@ static void lock_swapdevices(void) /* This is called after saving image so modif * would happen on next reboot -- corrupting data. * * Note: The buffer we allocate to use to write the suspend header is - * not freed; its not needed since system is going down anyway - * (plus it causes oops and I'm lazy^H^H^H^Htoo busy). + * not freed; its not needed since the system is going down anyway + * (plus it causes an oops and I'm lazy^H^H^H^Htoo busy). */ static int write_suspend_image(void) { @@ -341,6 +341,7 @@ static int write_suspend_image(void) printk("H"); BUG_ON (sizeof(struct suspend_header) > PAGE_SIZE-sizeof(swp_entry_t)); BUG_ON (sizeof(union diskpage) != PAGE_SIZE); + BUG_ON (sizeof(struct link) != PAGE_SIZE); if (!(entry = get_swap_page()).val) panic( "\nNot enough swapspace when writing header" ); if (swapfile_used[swp_type(entry)] != SWAPFILE_SUSPEND) @@ -838,23 +839,23 @@ static int relocate_pagedir(void) static int sanity_check_failed(char *reason) { - printk(KERN_ERR "%s%s\n",name_resume,reason); + printk(KERN_ERR "%s%s\n", name_resume, reason); return -EPERM; } static int sanity_check(struct suspend_header *sh) { - if(sh->version_code != LINUX_VERSION_CODE) + if (sh->version_code != LINUX_VERSION_CODE) return sanity_check_failed("Incorrect kernel version"); - if(sh->num_physpages != num_physpages) + if (sh->num_physpages != num_physpages) return sanity_check_failed("Incorrect memory size"); - if(strncmp(sh->machine, system_utsname.machine, 8)) + if (strncmp(sh->machine, system_utsname.machine, 8)) return sanity_check_failed("Incorrect machine type"); - if(strncmp(sh->version, system_utsname.version, 20)) + if (strncmp(sh->version, system_utsname.version, 20)) return sanity_check_failed("Incorrect version"); - if(sh->num_cpus != num_online_cpus()) + if (sh->num_cpus != num_online_cpus()) return sanity_check_failed("Incorrect number of cpus"); - if(sh->page_size != PAGE_SIZE) + if (sh->page_size != PAGE_SIZE) return sanity_check_failed("Incorrect PAGE_SIZE"); return 0; } -- cgit v1.2.3 From 0c2d119562483938d5635e20bdc548715fc20e12 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:41:41 -0800 Subject: [PATCH] Allow software_suspend to fail From: Pavel Machek software_suspend() can fail for quite a lot of reasons (for example not enough swapspace). However current interface returned void, so you could not propagate error back to userland. This fixes it. Plus __read_suspend_image() is only done during init time, so we might as well mark it __init. --- drivers/macintosh/via-pmu.c | 2 -- include/linux/suspend.h | 26 +++++++++++++++++++------- kernel/power/swsusp.c | 35 +++++++++++++++++------------------ kernel/sys.c | 8 +++----- 4 files changed, 39 insertions(+), 32 deletions(-) (limited to 'include/linux') diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 40ca8ea7f3a2..99007e8a3981 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -2288,8 +2288,6 @@ restore_via_state(void) } extern long sys_sync(void); -extern void pm_prepare_console(void); -extern void pm_restore_console(void); static int __pmac pmac_suspend_devices(void) diff --git a/include/linux/suspend.h b/include/linux/suspend.h index cd90591947bc..d0cdc77fa44e 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -42,30 +42,42 @@ extern int shrink_mem(void); /* mm/page_alloc.c */ extern void drain_local_pages(void); +/* kernel/power/swsusp.c */ +extern int software_suspend(void); + extern unsigned int nr_copy_pages __nosavedata; extern suspend_pagedir_t *pagedir_nosave __nosavedata; -#endif /* CONFIG_PM */ - -#ifdef CONFIG_SOFTWARE_SUSPEND - -extern unsigned char software_suspend_enabled; -extern void software_suspend(void); #else /* CONFIG_SOFTWARE_SUSPEND */ -static inline void software_suspend(void) +static inline int software_suspend(void) { printk("Warning: fake suspend called\n"); + return -EPERM; } +#define software_resume() do { } while(0) #endif /* CONFIG_SOFTWARE_SUSPEND */ #ifdef CONFIG_PM extern void refrigerator(unsigned long); +extern int freeze_processes(void); +extern void thaw_processes(void); + +extern int pm_prepare_console(void); +extern void pm_restore_console(void); #else static inline void refrigerator(unsigned long flag) { +} +static inline int freeze_processes(void) +{ + return 0; +} +static inline void thaw_processes(void) +{ + } #endif /* CONFIG_PM */ diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index b233f924a3ba..1577c3ed5295 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -677,11 +677,22 @@ void do_magic_suspend_2(void) mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME); } -static void do_software_suspend(void) +/* + * This is main interface to the outside world. It needs to be + * called from process context. + */ +int software_suspend(void) { + int res; + if (!software_suspend_enabled) + return -EAGAIN; + + software_suspend_enabled = 0; + might_sleep(); + if (arch_prepare_suspend()) { printk("%sArchitecture failed to prepare\n", name_suspend); - return; + return -EPERM; } if (pm_prepare_console()) printk( "%sCan't allocate a console... proceeding\n", name_suspend); @@ -711,24 +722,12 @@ static void do_software_suspend(void) */ do_magic(0); thaw_processes(); - } + } else + res = -EBUSY; software_suspend_enabled = 1; MDELAY(1000); pm_restore_console(); -} - -/* - * This is main interface to the outside world. It needs to be - * called from process context. - */ -void software_suspend(void) -{ - if(!software_suspend_enabled) - return; - - software_suspend_enabled = 0; - might_sleep(); - do_software_suspend(); + return res; } /* More restore stuff */ @@ -898,7 +897,7 @@ static int bdev_write_page(struct block_device *bdev, long pos, void *buf) extern dev_t __init name_to_dev_t(const char *line); -static int __read_suspend_image(struct block_device *bdev, union diskpage *cur, int noresume) +static int __init __read_suspend_image(struct block_device *bdev, union diskpage *cur, int noresume) { swp_entry_t next; int i, nr_pgdir_pages; diff --git a/kernel/sys.c b/kernel/sys.c index 2e40d516fd75..f24afd6fe4b1 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -475,13 +475,11 @@ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user #ifdef CONFIG_SOFTWARE_SUSPEND case LINUX_REBOOT_CMD_SW_SUSPEND: - if (!software_suspend_enabled) { + { + int ret = software_suspend(); unlock_kernel(); - return -EAGAIN; + return ret; } - software_suspend(); - do_exit(0); - break; #endif default: -- cgit v1.2.3 From 076cf989db79ff1957fd8bcf57d75d6555158055 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:41:59 -0800 Subject: [PATCH] hugetlbfs directory entry cleanup From: Anton Blanchard hugetlbfs is doing strange things with directory sizes. Al says there is no semantics for reported size of directories so we can remove this code. --- fs/hugetlbfs/inode.c | 6 ------ include/linux/hugetlb.h | 2 -- 2 files changed, 8 deletions(-) (limited to 'include/linux') diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 416a3dac23c1..c3e6a6b54063 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -425,7 +425,6 @@ static int hugetlbfs_mknod(struct inode *dir, } inode = hugetlbfs_get_inode(dir->i_sb, current->fsuid, gid, mode, dev); if (inode) { - dir->i_size += PSEUDO_DIRENT_SIZE; dir->i_ctime = dir->i_mtime = CURRENT_TIME; d_instantiate(dentry, inode); dget(dentry); /* Extra count - pin the dentry in core */ @@ -470,7 +469,6 @@ static int hugetlbfs_symlink(struct inode *dir, } else iput(inode); } - dir->i_size += PSEUDO_DIRENT_SIZE; dir->i_ctime = dir->i_mtime = CURRENT_TIME; return error; @@ -507,7 +505,6 @@ static int hugetlbfs_link(struct dentry *old_dentry, { struct inode *inode = old_dentry->d_inode; - dir->i_size += PSEUDO_DIRENT_SIZE; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; inode->i_nlink++; atomic_inc(&inode->i_count); @@ -520,7 +517,6 @@ static int hugetlbfs_unlink(struct inode *dir, struct dentry *dentry) { struct inode *inode = dentry->d_inode; - dir->i_size -= PSEUDO_DIRENT_SIZE; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; inode->i_nlink--; dput(dentry); @@ -554,8 +550,6 @@ static int hugetlbfs_rename(struct inode *old_dir, struct dentry *old_dentry, new_dir->i_nlink++; } - old_dir->i_size -= PSEUDO_DIRENT_SIZE; - new_dir->i_size += PSEUDO_DIRENT_SIZE; old_dir->i_ctime = old_dir->i_mtime = new_dir->i_ctime = new_dir->i_mtime = inode->i_ctime = CURRENT_TIME; return 0; diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 72bda668895b..a88f16ccdc5a 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -95,8 +95,6 @@ static inline struct hugetlbfs_sb_info *HUGETLBFS_SB(struct super_block *sb) return sb->s_fs_info; } -#define PSEUDO_DIRENT_SIZE 20 - extern struct file_operations hugetlbfs_file_operations; extern struct vm_operations_struct hugetlb_vm_ops; struct file *hugetlb_zero_setup(size_t); -- cgit v1.2.3 From f70ceb5a2fe6380ce61e23111458e843448d60b9 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:43:09 -0800 Subject: [PATCH] console: support for > 127 chars From: Nigel Cunningham Change the console code to support up to 256 (maybe 255?) columns. --- drivers/char/vt.c | 4 ++-- include/linux/selection.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/drivers/char/vt.c b/drivers/char/vt.c index dff05a88fb6d..fd00ee26e893 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -3062,13 +3062,13 @@ unsigned short *screen_pos(int currcons, int w_offset, int viewed) return screenpos(currcons, 2 * w_offset, viewed); } -void getconsxy(int currcons, char *p) +void getconsxy(int currcons, unsigned char *p) { p[0] = x; p[1] = y; } -void putconsxy(int currcons, char *p) +void putconsxy(int currcons, unsigned char *p) { gotoxy(currcons, p[0], p[1]); set_cursor(currcons); diff --git a/include/linux/selection.h b/include/linux/selection.h index a949695af3c5..fd34cfa5f5ef 100644 --- a/include/linux/selection.h +++ b/include/linux/selection.h @@ -36,8 +36,8 @@ extern u16 screen_glyph(int currcons, int offset); extern void complement_pos(int currcons, int offset); extern void invert_screen(int currcons, int offset, int count, int shift); -extern void getconsxy(int currcons, char *p); -extern void putconsxy(int currcons, char *p); +extern void getconsxy(int currcons, unsigned char *p); +extern void putconsxy(int currcons, unsigned char *p); extern u16 vcs_scr_readw(int currcons, const u16 *org); extern void vcs_scr_writew(int currcons, u16 val, u16 *org); -- cgit v1.2.3 From 73027d993d79480b7117c2a7e59c81629d10b0cf Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:43:18 -0800 Subject: [PATCH] remove valid_addr_bitmap From: William Lee Irwin III ->valid_addr_bitmap is initialized nowhere. Any kern_addr_valid() testing it returns 0 unconditionally. This patch converts kern_addr_valid() implementations using it to return 0 as per the above and removes it from structures and zone initialization. Untested (not even compiletested), though a similar patch also nuking d_validate() was in use in -wli for several months. --- include/asm-alpha/mmzone.h | 5 ++--- include/asm-i386/mmzone.h | 8 ++------ include/asm-mips/mmzone.h | 5 ++--- include/asm-ppc64/mmzone.h | 7 ++----- include/linux/mmzone.h | 1 - mm/page_alloc.c | 20 -------------------- 6 files changed, 8 insertions(+), 38 deletions(-) (limited to 'include/linux') diff --git a/include/asm-alpha/mmzone.h b/include/asm-alpha/mmzone.h index 36e3130c6696..ce75633b5052 100644 --- a/include/asm-alpha/mmzone.h +++ b/include/asm-alpha/mmzone.h @@ -72,9 +72,8 @@ PLAT_NODE_DATA_LOCALNR(unsigned long p, int n) ((unsigned long)__va(NODE_DATA(kvaddr_to_nid(kaddr))->node_start_pfn \ << PAGE_SHIFT)) -#define kern_addr_valid(kaddr) \ - test_bit(local_mapnr(kaddr), \ - NODE_DATA(kvaddr_to_nid(kaddr))->valid_addr_bitmap) +/* XXX: FIXME -- wli */ +#define kern_addr_valid(kaddr) (0) #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) diff --git a/include/asm-i386/mmzone.h b/include/asm-i386/mmzone.h index 8587d7e3a2ae..1bd79dfb3c9a 100644 --- a/include/asm-i386/mmzone.h +++ b/include/asm-i386/mmzone.h @@ -62,12 +62,8 @@ extern struct pglist_data *node_data[]; (__pfn - node_start_pfn(pfn_to_nid(__pfn))); \ }) -#define kern_addr_valid(kaddr) \ -({ \ - unsigned long __kaddr = (unsigned long)(kaddr); \ - pg_data_t *__pgdat = NODE_DATA(kvaddr_to_nid(__kaddr)); \ - test_bit(local_mapnr(__kaddr), __pgdat->valid_addr_bitmap); \ -}) +/* XXX: FIXME -- wli */ +#define kern_addr_valid(kaddr) (0) #define pfn_to_page(pfn) \ ({ \ diff --git a/include/asm-mips/mmzone.h b/include/asm-mips/mmzone.h index cba337b07be1..69cb153bb254 100644 --- a/include/asm-mips/mmzone.h +++ b/include/asm-mips/mmzone.h @@ -75,9 +75,8 @@ extern plat_pg_data_t *plat_node_data[]; (((unsigned long)ADDR_TO_MAPBASE((kaddr)) - PAGE_OFFSET) / \ sizeof(struct page)))) -#define kern_addr_valid(addr) ((KVADDR_TO_NID((unsigned long)addr) > \ - -1) ? 0 : (test_bit(LOCAL_MAP_NR((addr)), \ - NODE_DATA(KVADDR_TO_NID((unsigned long)addr))->valid_addr_bitmap))) +/* XXX: FIXME -- wli */ +#define kern_addr_valid(addr) (0) #define pfn_to_page(pfn) (mem_map + (pfn)) #define page_to_pfn(page) \ diff --git a/include/asm-ppc64/mmzone.h b/include/asm-ppc64/mmzone.h index 7a305c682693..7503c373f55e 100644 --- a/include/asm-ppc64/mmzone.h +++ b/include/asm-ppc64/mmzone.h @@ -72,11 +72,8 @@ static inline int pa_to_nid(unsigned long pa) #define local_mapnr(kvaddr) \ ( (__pa(kvaddr) >> PAGE_SHIFT) - node_start_pfn(kvaddr_to_nid(kvaddr)) -#if 0 -/* XXX fix - Anton */ -#define kern_addr_valid(kaddr) test_bit(local_mapnr(kaddr), \ - NODE_DATA(kvaddr_to_nid(kaddr))->valid_addr_bitmap) -#endif +/* XXX fix - Anton - and wli */ +#define kern_addr_valid(kaddr) (0) /* Written this way to avoid evaluating arguments twice */ #define discontigmem_pfn_to_page(pfn) \ diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 66cbaa36d878..71f2f39cae0f 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -205,7 +205,6 @@ typedef struct pglist_data { struct zonelist node_zonelists[MAX_NR_ZONES]; int nr_zones; struct page *node_mem_map; - unsigned long *valid_addr_bitmap; struct bootmem_data *bdata; unsigned long node_start_pfn; unsigned long node_present_pages; /* total number of physical pages */ diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 21cdc12dff7f..0a6832b028b5 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1182,24 +1182,6 @@ static void __init calculate_zone_totalpages(struct pglist_data *pgdat, printk("On node %d totalpages: %lu\n", pgdat->node_id, realtotalpages); } -/* - * Get space for the valid bitmap. - */ -static void __init calculate_zone_bitmap(struct pglist_data *pgdat, - unsigned long *zones_size) -{ - unsigned long size = 0; - int i; - - for (i = 0; i < MAX_NR_ZONES; i++) - size += zones_size[i]; - size = LONG_ALIGN((size + 7) >> 3); - if (size) { - pgdat->valid_addr_bitmap = - (unsigned long *)alloc_bootmem_node(pgdat, size); - memset(pgdat->valid_addr_bitmap, 0, size); - } -} /* * Initially all pages are reserved - free ones are freed @@ -1393,8 +1375,6 @@ void __init free_area_init_node(int nid, struct pglist_data *pgdat, free_area_init_core(pgdat, zones_size, zholes_size); memblk_set_online(node_to_memblk(nid)); - - calculate_zone_bitmap(pgdat, zones_size); } #ifndef CONFIG_DISCONTIGMEM -- cgit v1.2.3 From 32a0251f11dee59d917759b443d209d998f1a3a5 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:43:35 -0800 Subject: [PATCH] initialise cpu_vm_mask in init_mm From: Anton Blanchard Some architectures use cpu_vm_mask to optimise TLB flushes. On ppc64 we are now using a common flush infrastructure that handles both userspace and kernelspace (vmalloc) pages. In order to avoid triggering this optimisation we need to mark the init mm as having scheduled on all cpus. Things currently work by luck (we check for the cpu only having run on the local cpu, and the field is initialised to 0), but it would be safer to initialise it CPU_MASK_ALL. --- include/linux/init_task.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 59d4d291d455..f9708adb1d47 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -40,6 +40,7 @@ .mmap_sem = __RWSEM_INITIALIZER(name.mmap_sem), \ .page_table_lock = SPIN_LOCK_UNLOCKED, \ .mmlist = LIST_HEAD_INIT(name.mmlist), \ + .cpu_vm_mask = CPU_MASK_ALL, \ .default_kioctx = INIT_KIOCTX(name.default_kioctx, name), \ } -- cgit v1.2.3 From 62c10f9eb2213c1850f26ea51b4efa6396696d68 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:44:38 -0800 Subject: [PATCH] md: Change the way the name of an md device is printed in error messages. From: NeilBrown Instead of using ("md%d", mdidx(mddev)), we now use ("%s", mdname(mddev)) where mdname is the disk_name field in the associated gendisk structure. This allows future flexability in naming. --- drivers/md/md.c | 132 +++++++++++++++++++++++----------------------- drivers/md/multipath.c | 30 +++++------ drivers/md/raid0.c | 4 +- drivers/md/raid1.c | 30 +++++------ drivers/md/raid5.c | 40 +++++++------- drivers/md/raid6main.c | 42 +++++++-------- include/linux/raid/md_k.h | 4 ++ 7 files changed, 142 insertions(+), 140 deletions(-) (limited to 'include/linux') diff --git a/drivers/md/md.c b/drivers/md/md.c index e273a42954f7..616eb4f4898d 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -994,10 +994,10 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) same_pdev = match_dev_unit(mddev, rdev); if (same_pdev) printk(KERN_WARNING - "md%d: WARNING: %s appears to be on the same physical" + "%s: WARNING: %s appears to be on the same physical" " disk as %s. True\n protection against single-disk" " failure might be compromised.\n", - mdidx(mddev), bdevname(rdev->bdev,b), + mdname(mddev), bdevname(rdev->bdev,b), bdevname(same_pdev->bdev,b2)); /* Verify rdev->desc_nr is unique. @@ -1177,7 +1177,7 @@ void md_print_devices(void) printk("md: * *\n"); printk("md: **********************************\n"); ITERATE_MDDEV(mddev,tmp) { - printk("md%d: ", mdidx(mddev)); + printk("%s: ", mdname(mddev)); ITERATE_RDEV(mddev,rdev,tmp2) printk("<%s>", bdevname(rdev->bdev,b)); @@ -1257,8 +1257,8 @@ repeat: return; dprintk(KERN_INFO - "md: updating md%d RAID superblock on device (in sync %d)\n", - mdidx(mddev),mddev->in_sync); + "md: updating %s RAID superblock on device (in sync %d)\n", + mdname(mddev),mddev->in_sync); err = 0; ITERATE_RDEV(mddev,rdev,tmp) { @@ -1424,8 +1424,8 @@ static int analyze_sbs(mddev_t * mddev) if (mddev->major_version != MD_MAJOR_VERSION || mddev->minor_version > MD_MINOR_VERSION) { printk(KERN_ALERT - "md: md%d: unsupported raid array version %d.%d.%d\n", - mdidx(mddev), mddev->major_version, + "md: %s: unsupported raid array version %d.%d.%d\n", + mdname(mddev), mddev->major_version, mddev->minor_version, mddev->patch_version); goto abort; } @@ -1433,9 +1433,9 @@ static int analyze_sbs(mddev_t * mddev) if ((mddev->recovery_cp != MaxSector) && ((mddev->level == 1) || ((mddev->level >= 4) && (mddev->level <= 6)))) - printk(KERN_ERR "md: md%d: raid array is not clean" + printk(KERN_ERR "md: %s: raid array is not clean" " -- starting background reconstruction\n", - mdidx(mddev)); + mdname(mddev)); return 0; abort: @@ -1660,8 +1660,8 @@ static int restart_array(mddev_t *mddev) mddev->ro = 0; set_disk_ro(disk, 0); - printk(KERN_INFO "md: md%d switched to read-write mode.\n", - mdidx(mddev)); + printk(KERN_INFO "md: %s switched to read-write mode.\n", + mdname(mddev)); /* * Kick recovery or resync if necessary */ @@ -1669,8 +1669,8 @@ static int restart_array(mddev_t *mddev) md_wakeup_thread(mddev->thread); err = 0; } else { - printk(KERN_ERR "md: md%d has no personality assigned.\n", - mdidx(mddev)); + printk(KERN_ERR "md: %s has no personality assigned.\n", + mdname(mddev)); err = -EINVAL; } @@ -1685,7 +1685,7 @@ static int do_md_stop(mddev_t * mddev, int ro) if (mddev->pers) { if (atomic_read(&mddev->active)>2) { - printk("md: md%d still in use.\n",mdidx(mddev)); + printk("md: %s still in use.\n",mdname(mddev)); return -EBUSY; } @@ -1727,7 +1727,7 @@ static int do_md_stop(mddev_t * mddev, int ro) */ if (!ro) { struct gendisk *disk; - printk(KERN_INFO "md: md%d stopped.\n", mdidx(mddev)); + printk(KERN_INFO "md: %s stopped.\n", mdname(mddev)); export_array(mddev); @@ -1736,8 +1736,8 @@ static int do_md_stop(mddev_t * mddev, int ro) if (disk) set_capacity(disk, 0); } else - printk(KERN_INFO "md: md%d switched to read-only mode.\n", - mdidx(mddev)); + printk(KERN_INFO "md: %s switched to read-only mode.\n", + mdname(mddev)); err = 0; out: return err; @@ -1816,16 +1816,16 @@ static void autorun_devices(void) break; } if (mddev_lock(mddev)) - printk(KERN_WARNING "md: md%d locked, cannot run\n", - mdidx(mddev)); + printk(KERN_WARNING "md: %s locked, cannot run\n", + mdname(mddev)); else if (mddev->raid_disks || mddev->major_version || !list_empty(&mddev->disks)) { printk(KERN_WARNING - "md: md%d already running, cannot run %s\n", - mdidx(mddev), bdevname(rdev0->bdev,b)); + "md: %s already running, cannot run %s\n", + mdname(mddev), bdevname(rdev0->bdev,b)); mddev_unlock(mddev); } else if (rdev0->preferred_minor >= 0 && rdev0->preferred_minor < MAX_MD_DEVS) { - printk(KERN_INFO "md: created md%d\n", mdidx(mddev)); + printk(KERN_INFO "md: created %s\n", mdname(mddev)); ITERATE_RDEV_GENERIC(candidates,rdev,tmp) { list_del_init(&rdev->same_set); if (bind_rdev_to_array(rdev, mddev)) @@ -2059,8 +2059,8 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) int err; if (!mddev->pers->hot_add_disk) { printk(KERN_WARNING - "md%d: personality does not support diskops!\n", - mdidx(mddev)); + "%s: personality does not support diskops!\n", + mdname(mddev)); return -EINVAL; } rdev = md_import_device(dev, mddev->major_version, @@ -2085,8 +2085,8 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) * for major_version==0 superblocks */ if (mddev->major_version != 0) { - printk(KERN_WARNING "md%d: ADD_NEW_DISK not supported\n", - mdidx(mddev)); + printk(KERN_WARNING "%s: ADD_NEW_DISK not supported\n", + mdname(mddev)); return -EINVAL; } @@ -2140,8 +2140,8 @@ static int hot_generate_error(mddev_t * mddev, dev_t dev) if (!mddev->pers) return -ENODEV; - printk(KERN_INFO "md: trying to generate %s error in md%d ... \n", - __bdevname(dev, b), mdidx(mddev)); + printk(KERN_INFO "md: trying to generate %s error in %s ... \n", + __bdevname(dev, b), mdname(mddev)); rdev = find_rdev(mddev, dev); if (!rdev) { @@ -2175,8 +2175,8 @@ static int hot_remove_disk(mddev_t * mddev, dev_t dev) if (!mddev->pers) return -ENODEV; - printk(KERN_INFO "md: trying to remove %s from md%d ... \n", - __bdevname(dev, b), mdidx(mddev)); + printk(KERN_INFO "md: trying to remove %s from %s ... \n", + __bdevname(dev, b), mdname(mddev)); rdev = find_rdev(mddev, dev); if (!rdev) @@ -2190,8 +2190,8 @@ static int hot_remove_disk(mddev_t * mddev, dev_t dev) return 0; busy: - printk(KERN_WARNING "md: cannot remove active disk %s from md%d ... \n", - bdevname(rdev->bdev,b), mdidx(mddev)); + printk(KERN_WARNING "md: cannot remove active disk %s from %s ... \n", + bdevname(rdev->bdev,b), mdname(mddev)); return -EBUSY; } @@ -2205,19 +2205,19 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) if (!mddev->pers) return -ENODEV; - printk(KERN_INFO "md: trying to hot-add %s to md%d ... \n", - __bdevname(dev, b), mdidx(mddev)); + printk(KERN_INFO "md: trying to hot-add %s to %s ... \n", + __bdevname(dev, b), mdname(mddev)); if (mddev->major_version != 0) { - printk(KERN_WARNING "md%d: HOT_ADD may only be used with" + printk(KERN_WARNING "%s: HOT_ADD may only be used with" " version-0 superblocks.\n", - mdidx(mddev)); + mdname(mddev)); return -EINVAL; } if (!mddev->pers->hot_add_disk) { printk(KERN_WARNING - "md%d: personality does not support diskops!\n", - mdidx(mddev)); + "%s: personality does not support diskops!\n", + mdname(mddev)); return -EINVAL; } @@ -2235,8 +2235,8 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) if (size < mddev->size) { printk(KERN_WARNING - "md%d: disk size %llu blocks < array size %llu\n", - mdidx(mddev), (unsigned long long)size, + "%s: disk size %llu blocks < array size %llu\n", + mdname(mddev), (unsigned long long)size, (unsigned long long)mddev->size); err = -ENOSPC; goto abort_export; @@ -2244,8 +2244,8 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) if (rdev->faulty) { printk(KERN_WARNING - "md: can not hot-add faulty %s disk to md%d!\n", - bdevname(rdev->bdev,b), mdidx(mddev)); + "md: can not hot-add faulty %s disk to %s!\n", + bdevname(rdev->bdev,b), mdname(mddev)); err = -EINVAL; goto abort_export; } @@ -2259,8 +2259,8 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) */ if (rdev->desc_nr == mddev->max_disks) { - printk(KERN_WARNING "md%d: can not hot-add to full array!\n", - mdidx(mddev)); + printk(KERN_WARNING "%s: can not hot-add to full array!\n", + mdname(mddev)); err = -EBUSY; goto abort_unbind_export; } @@ -2442,15 +2442,15 @@ static int md_ioctl(struct inode *inode, struct file *file, if (!list_empty(&mddev->disks)) { printk(KERN_WARNING - "md: array md%d already has disks!\n", - mdidx(mddev)); + "md: array %s already has disks!\n", + mdname(mddev)); err = -EBUSY; goto abort_unlock; } if (mddev->raid_disks) { printk(KERN_WARNING - "md: array md%d already initialised!\n", - mdidx(mddev)); + "md: array %s already initialised!\n", + mdname(mddev)); err = -EBUSY; goto abort_unlock; } @@ -2645,7 +2645,7 @@ int md_thread(void * arg) * Detach thread */ - daemonize(thread->name, mdidx(thread->mddev)); + daemonize(thread->name, mdname(thread->mddev)); current->exit_signal = SIGCHLD; allow_signal(SIGKILL); @@ -2759,8 +2759,8 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev) if (!rdev || rdev->faulty) return; - dprintk("md_error dev:(%d:%d), rdev:(%d:%d), (caller: %p,%p,%p,%p).\n", - MD_MAJOR,mdidx(mddev), + dprintk("md_error dev:%s, rdev:(%d:%d), (caller: %p,%p,%p,%p).\n", + mdname(mddev), MAJOR(rdev->bdev->bd_dev), MINOR(rdev->bdev->bd_dev), __builtin_return_address(0),__builtin_return_address(1), __builtin_return_address(2),__builtin_return_address(3)); @@ -2933,7 +2933,7 @@ static int md_seq_show(struct seq_file *seq, void *v) if (mddev_lock(mddev)!=0) return -EINTR; if (mddev->pers || mddev->raid_disks || !list_empty(&mddev->disks)) { - seq_printf(seq, "md%d : %sactive", mdidx(mddev), + seq_printf(seq, "%s : %sactive", mdname(mddev), mddev->pers ? "" : "in"); if (mddev->pers) { if (mddev->ro) @@ -3122,8 +3122,8 @@ static inline void md_enter_safemode(mddev_t *mddev) void md_handle_safemode(mddev_t *mddev) { if (signal_pending(current)) { - printk(KERN_INFO "md: md%d in immediate safe mode\n", - mdidx(mddev)); + printk(KERN_INFO "md: %s in immediate safe mode\n", + mdname(mddev)); mddev->safemode = 2; flush_signals(current); } @@ -3165,10 +3165,10 @@ static void md_do_sync(mddev_t *mddev) continue; if (mddev2->curr_resync && match_mddev_units(mddev,mddev2)) { - printk(KERN_INFO "md: delaying resync of md%d" - " until md%d has finished resync (they" + printk(KERN_INFO "md: delaying resync of %s" + " until %s has finished resync (they" " share one or more physical units)\n", - mdidx(mddev), mdidx(mddev2)); + mdname(mddev), mdname(mddev2)); if (mddev < mddev2) {/* arbitrarily yield */ mddev->curr_resync = 1; wake_up(&resync_wait); @@ -3189,7 +3189,7 @@ static void md_do_sync(mddev_t *mddev) max_sectors = mddev->size << 1; - printk(KERN_INFO "md: syncing RAID array md%d\n", mdidx(mddev)); + printk(KERN_INFO "md: syncing RAID array %s\n", mdname(mddev)); printk(KERN_INFO "md: minimum _guaranteed_ reconstruction speed:" " %d KB/sec/disc.\n", sysctl_speed_limit_min); printk(KERN_INFO "md: using maximum available idle IO bandwith " @@ -3222,8 +3222,8 @@ static void md_do_sync(mddev_t *mddev) if (j) printk(KERN_INFO - "md: resuming recovery of md%d from checkpoint.\n", - mdidx(mddev)); + "md: resuming recovery of %s from checkpoint.\n", + mdname(mddev)); while (j < max_sectors) { int sectors; @@ -3293,7 +3293,7 @@ static void md_do_sync(mddev_t *mddev) } } } - printk(KERN_INFO "md: md%d: sync done.\n",mdidx(mddev)); + printk(KERN_INFO "md: %s: sync done.\n",mdname(mddev)); /* * this also signals 'finished resyncing' to md_stop */ @@ -3308,8 +3308,8 @@ static void md_do_sync(mddev_t *mddev) mddev->curr_resync > mddev->recovery_cp) { if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { printk(KERN_INFO - "md: checkpointing recovery of md%d.\n", - mdidx(mddev)); + "md: checkpointing recovery of %s.\n", + mdname(mddev)); mddev->recovery_cp = mddev->curr_resync; } else mddev->recovery_cp = MaxSector; @@ -3429,11 +3429,11 @@ void md_check_recovery(mddev_t *mddev) set_bit(MD_RECOVERY_SYNC, &mddev->recovery); mddev->sync_thread = md_register_thread(md_do_sync, mddev, - "md%d_resync"); + "%s_resync"); if (!mddev->sync_thread) { - printk(KERN_ERR "md%d: could not start resync" + printk(KERN_ERR "%s: could not start resync" " thread...\n", - mdidx(mddev)); + mdname(mddev)); /* leave the spares where they are, it shouldn't hurt */ mddev->recovery = 0; } else { diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index e78c2b580cf3..bf9980a8b1fd 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -389,8 +389,8 @@ static int multipath_run (mddev_t *mddev) struct list_head *tmp; if (mddev->level != LEVEL_MULTIPATH) { - printk("multipath: md%d: raid level not set to multipath IO (%d)\n", - mdidx(mddev), mddev->level); + printk("multipath: %s: raid level not set to multipath IO (%d)\n", + mdname(mddev), mddev->level); goto out; } /* @@ -403,8 +403,8 @@ static int multipath_run (mddev_t *mddev) mddev->private = conf; if (!conf) { printk(KERN_ERR - "multipath: couldn't allocate memory for md%d\n", - mdidx(mddev)); + "multipath: couldn't allocate memory for %s\n", + mdname(mddev)); goto out; } memset(conf, 0, sizeof(*conf)); @@ -413,8 +413,8 @@ static int multipath_run (mddev_t *mddev) GFP_KERNEL); if (!conf->multipaths) { printk(KERN_ERR - "multipath: couldn't allocate memory for md%d\n", - mdidx(mddev)); + "multipath: couldn't allocate memory for %s\n", + mdname(mddev)); goto out_free_conf; } memset(conf->multipaths, 0, sizeof(struct multipath_info)*mddev->raid_disks); @@ -448,8 +448,8 @@ static int multipath_run (mddev_t *mddev) conf->device_lock = SPIN_LOCK_UNLOCKED; if (!conf->working_disks) { - printk(KERN_ERR "multipath: no operational IO paths for md%d\n", - mdidx(mddev)); + printk(KERN_ERR "multipath: no operational IO paths for %s\n", + mdname(mddev)); goto out_free_conf; } mddev->degraded = conf->raid_disks = conf->working_disks; @@ -459,25 +459,23 @@ static int multipath_run (mddev_t *mddev) NULL); if (conf->pool == NULL) { printk(KERN_ERR - "multipath: couldn't allocate memory for md%d\n", - mdidx(mddev)); + "multipath: couldn't allocate memory for %s\n", + mdname(mddev)); goto out_free_conf; } { - const char * name = "md%d_multipath"; - - mddev->thread = md_register_thread(multipathd, mddev, name); + mddev->thread = md_register_thread(multipathd, mddev, "%s_multipath"); if (!mddev->thread) { printk(KERN_ERR "multipath: couldn't allocate thread" - " for md%d\n", mdidx(mddev)); + " for %s\n", mdname(mddev)); goto out_free_conf; } } printk(KERN_INFO - "multipath: array md%d active with %d out of %d IO paths\n", - mdidx(mddev), conf->working_disks, mddev->raid_disks); + "multipath: array %s active with %d out of %d IO paths\n", + mdname(mddev), conf->working_disks, mddev->raid_disks); /* * Ok, everything is just fine now */ diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 5f472b5466d6..cf71910c23de 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -240,8 +240,8 @@ static int raid0_run (mddev_t *mddev) mdk_rdev_t *rdev; struct list_head *tmp; - printk("md%d: setting max_sectors to %d, segment boundary to %d\n", - mdidx(mddev), + printk("%s: setting max_sectors to %d, segment boundary to %d\n", + mdname(mddev), mddev->chunk_size >> 9, (mddev->chunk_size>>1)-1); blk_queue_max_sectors(mddev->queue, mddev->chunk_size >> 9); diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index f0540dc72f36..160c004bd935 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1052,8 +1052,8 @@ static int run(mddev_t *mddev) struct list_head *tmp; if (mddev->level != 1) { - printk("raid1: md%d: raid level not set to mirroring (%d)\n", - mdidx(mddev), mddev->level); + printk("raid1: %s: raid level not set to mirroring (%d)\n", + mdname(mddev), mddev->level); goto out; } /* @@ -1064,16 +1064,16 @@ static int run(mddev_t *mddev) conf = kmalloc(sizeof(conf_t), GFP_KERNEL); mddev->private = conf; if (!conf) { - printk(KERN_ERR "raid1: couldn't allocate memory for md%d\n", - mdidx(mddev)); + printk(KERN_ERR "raid1: couldn't allocate memory for %s\n", + mdname(mddev)); goto out; } memset(conf, 0, sizeof(*conf)); conf->mirrors = kmalloc(sizeof(struct mirror_info)*mddev->raid_disks, GFP_KERNEL); if (!conf->mirrors) { - printk(KERN_ERR "raid1: couldn't allocate memory for md%d\n", - mdidx(mddev)); + printk(KERN_ERR "raid1: couldn't allocate memory for %s\n", + mdname(mddev)); goto out_free_conf; } memset(conf->mirrors, 0, sizeof(struct mirror_info)*mddev->raid_disks); @@ -1081,8 +1081,8 @@ static int run(mddev_t *mddev) conf->r1bio_pool = mempool_create(NR_RAID1_BIOS, r1bio_pool_alloc, r1bio_pool_free, mddev); if (!conf->r1bio_pool) { - printk(KERN_ERR "raid1: couldn't allocate memory for md%d\n", - mdidx(mddev)); + printk(KERN_ERR "raid1: couldn't allocate memory for %s\n", + mdname(mddev)); goto out_free_conf; } @@ -1121,8 +1121,8 @@ static int run(mddev_t *mddev) init_waitqueue_head(&conf->wait_resume); if (!conf->working_disks) { - printk(KERN_ERR "raid1: no operational mirrors for md%d\n", - mdidx(mddev)); + printk(KERN_ERR "raid1: no operational mirrors for %s\n", + mdname(mddev)); goto out_free_conf; } @@ -1150,17 +1150,17 @@ static int run(mddev_t *mddev) { - mddev->thread = md_register_thread(raid1d, mddev, "md%d_raid1"); + mddev->thread = md_register_thread(raid1d, mddev, "%s_raid1"); if (!mddev->thread) { printk(KERN_ERR - "raid1: couldn't allocate thread for md%d\n", - mdidx(mddev)); + "raid1: couldn't allocate thread for %s\n", + mdname(mddev)); goto out_free_conf; } } printk(KERN_INFO - "raid1: raid set md%d active with %d out of %d mirrors\n", - mdidx(mddev), mddev->raid_disks - mddev->degraded, + "raid1: raid set %s active with %d out of %d mirrors\n", + mdname(mddev), mddev->raid_disks - mddev->degraded, mddev->raid_disks); /* * Ok, everything is just fine now diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 20a71af43e33..300f17b50280 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1485,7 +1485,7 @@ static int run (mddev_t *mddev) struct list_head *tmp; if (mddev->level != 5 && mddev->level != 4) { - printk("raid5: md%d: raid level not set to 4/5 (%d)\n", mdidx(mddev), mddev->level); + printk("raid5: %s: raid level not set to 4/5 (%d)\n", mdname(mddev), mddev->level); return -EIO; } @@ -1511,7 +1511,7 @@ static int run (mddev_t *mddev) mddev->queue->unplug_fn = raid5_unplug_device; - PRINTK("raid5: run(md%d) called.\n", mdidx(mddev)); + PRINTK("raid5: run(%s) called.\n", mdname(mddev)); ITERATE_RDEV(mddev,rdev,tmp) { raid_disk = rdev->raid_disk; @@ -1543,37 +1543,37 @@ static int run (mddev_t *mddev) conf->max_nr_stripes = NR_STRIPES; if (!conf->chunk_size || conf->chunk_size % 4) { - printk(KERN_ERR "raid5: invalid chunk size %d for md%d\n", - conf->chunk_size, mdidx(mddev)); + printk(KERN_ERR "raid5: invalid chunk size %d for %s\n", + conf->chunk_size, mdname(mddev)); goto abort; } if (conf->algorithm > ALGORITHM_RIGHT_SYMMETRIC) { printk(KERN_ERR - "raid5: unsupported parity algorithm %d for md%d\n", - conf->algorithm, mdidx(mddev)); + "raid5: unsupported parity algorithm %d for %s\n", + conf->algorithm, mdname(mddev)); goto abort; } if (mddev->degraded > 1) { - printk(KERN_ERR "raid5: not enough operational devices for md%d" + printk(KERN_ERR "raid5: not enough operational devices for %s" " (%d/%d failed)\n", - mdidx(mddev), conf->failed_disks, conf->raid_disks); + mdname(mddev), conf->failed_disks, conf->raid_disks); goto abort; } if (mddev->degraded == 1 && mddev->recovery_cp != MaxSector) { printk(KERN_ERR - "raid5: cannot start dirty degraded array for md%d\n", - mdidx(mddev)); + "raid5: cannot start dirty degraded array for %s\n", + mdname(mddev)); goto abort; } { - mddev->thread = md_register_thread(raid5d, mddev, "md%d_raid5"); + mddev->thread = md_register_thread(raid5d, mddev, "%s_raid5"); if (!mddev->thread) { printk(KERN_ERR - "raid5: couldn't allocate thread for md%d\n", - mdidx(mddev)); + "raid5: couldn't allocate thread for %s\n", + mdname(mddev)); goto abort; } } @@ -1586,18 +1586,18 @@ memory = conf->max_nr_stripes * (sizeof(struct stripe_head) + md_unregister_thread(mddev->thread); goto abort; } else - printk(KERN_INFO "raid5: allocated %dkB for md%d\n", - memory, mdidx(mddev)); + printk(KERN_INFO "raid5: allocated %dkB for %s\n", + memory, mdname(mddev)); if (mddev->degraded == 0) - printk("raid5: raid level %d set md%d active with %d out of %d" - " devices, algorithm %d\n", conf->level, mdidx(mddev), + printk("raid5: raid level %d set %s active with %d out of %d" + " devices, algorithm %d\n", conf->level, mdname(mddev), mddev->raid_disks-mddev->degraded, mddev->raid_disks, conf->algorithm); else - printk(KERN_ALERT "raid5: raid level %d set md%d active with %d" + printk(KERN_ALERT "raid5: raid level %d set %s active with %d" " out of %d devices, algorithm %d\n", conf->level, - mdidx(mddev), mddev->raid_disks - mddev->degraded, + mdname(mddev), mddev->raid_disks - mddev->degraded, mddev->raid_disks, conf->algorithm); print_raid5_conf(conf); @@ -1624,7 +1624,7 @@ abort: kfree(conf); } mddev->private = NULL; - printk(KERN_ALERT "raid5: failed to run raid set md%d\n", mdidx(mddev)); + printk(KERN_ALERT "raid5: failed to run raid set %s\n", mdname(mddev)); return -EIO; } diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c index c138686c73da..b3f1b842133f 100644 --- a/drivers/md/raid6main.c +++ b/drivers/md/raid6main.c @@ -1647,7 +1647,7 @@ static int run (mddev_t *mddev) struct list_head *tmp; if (mddev->level != 6) { - PRINTK("raid6: md%d: raid level not set to 6 (%d)\n", mdidx(mddev), mddev->level); + PRINTK("raid6: %s: raid level not set to 6 (%d)\n", mdname(mddev), mddev->level); return -EIO; } @@ -1673,7 +1673,7 @@ static int run (mddev_t *mddev) mddev->queue->unplug_fn = raid6_unplug_device; - PRINTK("raid6: run(md%d) called.\n", mdidx(mddev)); + PRINTK("raid6: run(%s) called.\n", mdname(mddev)); ITERATE_RDEV(mddev,rdev,tmp) { raid_disk = rdev->raid_disk; @@ -1706,42 +1706,42 @@ static int run (mddev_t *mddev) conf->max_nr_stripes = NR_STRIPES; if (conf->raid_disks < 4) { - printk(KERN_ERR "raid6: not enough configured devices for md%d (%d, minimum 4)\n", - mdidx(mddev), conf->raid_disks); + printk(KERN_ERR "raid6: not enough configured devices for %s (%d, minimum 4)\n", + mdname(mddev), conf->raid_disks); goto abort; } if (!conf->chunk_size || conf->chunk_size % 4) { - printk(KERN_ERR "raid6: invalid chunk size %d for md%d\n", - conf->chunk_size, mdidx(mddev)); + printk(KERN_ERR "raid6: invalid chunk size %d for %s\n", + conf->chunk_size, mdname(mddev)); goto abort; } if (conf->algorithm > ALGORITHM_RIGHT_SYMMETRIC) { printk(KERN_ERR - "raid6: unsupported parity algorithm %d for md%d\n", - conf->algorithm, mdidx(mddev)); + "raid6: unsupported parity algorithm %d for %s\n", + conf->algorithm, mdname(mddev)); goto abort; } if (mddev->degraded > 2) { - printk(KERN_ERR "raid6: not enough operational devices for md%d" + printk(KERN_ERR "raid6: not enough operational devices for %s" " (%d/%d failed)\n", - mdidx(mddev), conf->failed_disks, conf->raid_disks); + mdname(mddev), conf->failed_disks, conf->raid_disks); goto abort; } #if 0 /* FIX: For now */ if (mddev->degraded > 0 && mddev->recovery_cp != MaxSector) { - printk(KERN_ERR "raid6: cannot start dirty degraded array for md%d\n", mdidx(mddev)); + printk(KERN_ERR "raid6: cannot start dirty degraded array for %s\n", mdname(mddev)); goto abort; } #endif { - mddev->thread = md_register_thread(raid6d, mddev, "md%d_raid6"); + mddev->thread = md_register_thread(raid6d, mddev, "%s_raid6"); if (!mddev->thread) { printk(KERN_ERR - "raid6: couldn't allocate thread for md%d\n", - mdidx(mddev)); + "raid6: couldn't allocate thread for %s\n", + mdname(mddev)); goto abort; } } @@ -1755,18 +1755,18 @@ static int run (mddev_t *mddev) md_unregister_thread(mddev->thread); goto abort; } else - printk(KERN_INFO "raid6: allocated %dkB for md%d\n", - memory, mdidx(mddev)); + printk(KERN_INFO "raid6: allocated %dkB for %s\n", + memory, mdname(mddev)); if (mddev->degraded == 0) - printk(KERN_INFO "raid6: raid level %d set md%d active with %d out of %d" - " devices, algorithm %d\n", conf->level, mdidx(mddev), + printk(KERN_INFO "raid6: raid level %d set %s active with %d out of %d" + " devices, algorithm %d\n", conf->level, mdname(mddev), mddev->raid_disks-mddev->degraded, mddev->raid_disks, conf->algorithm); else - printk(KERN_ALERT "raid6: raid level %d set md%d active with %d" + printk(KERN_ALERT "raid6: raid level %d set %s active with %d" " out of %d devices, algorithm %d\n", conf->level, - mdidx(mddev), mddev->raid_disks - mddev->degraded, + mdname(mddev), mddev->raid_disks - mddev->degraded, mddev->raid_disks, conf->algorithm); print_raid6_conf(conf); @@ -1793,7 +1793,7 @@ abort: kfree(conf); } mddev->private = NULL; - printk(KERN_ALERT "raid6: failed to run raid set md%d\n", mdidx(mddev)); + printk(KERN_ALERT "raid6: failed to run raid set %s\n", mdname(mddev)); return -EIO; } diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index 7b6e12c45dc9..a89da5378b5f 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -281,6 +281,10 @@ static inline int mdidx (mddev_t * mddev) { return mddev->__minor; } +static inline char * mdname (mddev_t * mddev) +{ + return mddev->gendisk ? mddev->gendisk->disk_name : "mdX"; +} extern mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr); -- cgit v1.2.3 From 4c5736de7785f499aad01c87b568011aebc8ebf4 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:45:06 -0800 Subject: [PATCH] Remove memblks from the kernel From: "Martin J. Bligh" This patch removes memblks from the kernel ... we don't use them, and the NUMA API that was planning to use them when they were originally designed isn't going to use them anymore. They're just unnecessary added complexity now ... time for them to go. There's a slight complication in that ia64 uses something with a similar name for part of its memory layout, but Jes Sorensen kindly untangled them from each other for us. The patch with his modifications is below. Jes tested it on ia64, and I testbuilt it with every config in my arsenal. --- arch/i386/mach-default/topology.c | 4 ---- arch/i386/mach-es7000/topology.c | 4 ---- arch/ia64/kernel/acpi.c | 10 ++++----- arch/ia64/mm/discontig.c | 6 +++--- arch/ia64/mm/numa.c | 25 ++++------------------- drivers/base/Makefile | 2 +- drivers/base/memblk.c | 43 --------------------------------------- include/asm-alpha/topology.h | 3 --- include/asm-generic/topology.h | 6 ------ include/asm-i386/memblk.h | 23 --------------------- include/asm-i386/topology.h | 6 ------ include/asm-ia64/mmzone.h | 6 +++--- include/asm-ia64/numa.h | 4 ++-- include/asm-ia64/topology.h | 15 -------------- include/asm-ppc64/topology.h | 4 ---- include/asm-x86_64/memblk.h | 1 - include/asm-x86_64/topology.h | 2 -- include/linux/memblk.h | 32 ----------------------------- include/linux/mmzone.h | 29 -------------------------- mm/page_alloc.c | 2 -- 20 files changed, 18 insertions(+), 209 deletions(-) delete mode 100644 drivers/base/memblk.c delete mode 100644 include/asm-i386/memblk.h delete mode 100644 include/asm-x86_64/memblk.h delete mode 100644 include/linux/memblk.h (limited to 'include/linux') diff --git a/arch/i386/mach-default/topology.c b/arch/i386/mach-default/topology.c index cd6449567209..e96d8910ab52 100644 --- a/arch/i386/mach-default/topology.c +++ b/arch/i386/mach-default/topology.c @@ -34,10 +34,8 @@ struct i386_cpu cpu_devices[NR_CPUS]; #ifdef CONFIG_NUMA #include #include -#include struct i386_node node_devices[MAX_NUMNODES]; -struct i386_memblk memblk_devices[MAX_NR_MEMBLKS]; static int __init topology_init(void) { @@ -47,8 +45,6 @@ static int __init topology_init(void) arch_register_node(i); for (i = 0; i < NR_CPUS; i++) if (cpu_possible(i)) arch_register_cpu(i); - for (i = 0; i < num_online_memblks(); i++) - arch_register_memblk(i); return 0; } diff --git a/arch/i386/mach-es7000/topology.c b/arch/i386/mach-es7000/topology.c index cd6449567209..e96d8910ab52 100644 --- a/arch/i386/mach-es7000/topology.c +++ b/arch/i386/mach-es7000/topology.c @@ -34,10 +34,8 @@ struct i386_cpu cpu_devices[NR_CPUS]; #ifdef CONFIG_NUMA #include #include -#include struct i386_node node_devices[MAX_NUMNODES]; -struct i386_memblk memblk_devices[MAX_NR_MEMBLKS]; static int __init topology_init(void) { @@ -47,8 +45,6 @@ static int __init topology_init(void) arch_register_node(i); for (i = 0; i < NR_CPUS; i++) if (cpu_possible(i)) arch_register_cpu(i); - for (i = 0; i < num_online_memblks(); i++) - arch_register_memblk(i); return 0; } diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index fc9d6b958df1..2a88bf4619ba 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -409,7 +409,7 @@ acpi_numa_memory_affinity_init (struct acpi_table_memory_affinity *ma) pxm_bit_set(pxm); /* Insertion sort based on base address */ - pend = &node_memblk[num_memblks]; + pend = &node_memblk[num_node_memblks]; for (p = &node_memblk[0]; p < pend; p++) { if (paddr < p->start_paddr) break; @@ -421,7 +421,7 @@ acpi_numa_memory_affinity_init (struct acpi_table_memory_affinity *ma) p->start_paddr = paddr; p->size = size; p->nid = pxm; - num_memblks++; + num_node_memblks++; } void __init @@ -448,7 +448,7 @@ acpi_numa_arch_fixup (void) } /* set logical node id in memory chunk structure */ - for (i = 0; i < num_memblks; i++) + for (i = 0; i < num_node_memblks; i++) node_memblk[i].nid = pxm_to_nid_map[node_memblk[i].nid]; /* assign memory bank numbers for each chunk on each node */ @@ -456,7 +456,7 @@ acpi_numa_arch_fixup (void) int bank; bank = 0; - for (j = 0; j < num_memblks; j++) + for (j = 0; j < num_node_memblks; j++) if (node_memblk[j].nid == i) node_memblk[j].bank = bank++; } @@ -466,7 +466,7 @@ acpi_numa_arch_fixup (void) node_cpuid[i].nid = pxm_to_nid_map[node_cpuid[i].nid]; printk(KERN_INFO "Number of logical nodes in system = %d\n", numnodes); - printk(KERN_INFO "Number of memory chunks in system = %d\n", num_memblks); + printk(KERN_INFO "Number of memory chunks in system = %d\n", num_node_memblks); if (!slit_table) return; memset(numa_slit, -1, sizeof(numa_slit)); diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index 9f3976057afc..d1306576f8d8 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c @@ -419,14 +419,14 @@ void call_pernode_memory(unsigned long start, unsigned long len, void *arg) func = arg; - if (!num_memblks) { - /* No SRAT table, to assume one node (node 0) */ + if (!num_node_memblks) { + /* No SRAT table, so assume one node (node 0) */ if (start < end) (*func)(start, len, 0); return; } - for (i = 0; i < num_memblks; i++) { + for (i = 0; i < num_node_memblks; i++) { rs = max(start, node_memblk[i].start_paddr); re = min(end, node_memblk[i].start_paddr + node_memblk[i].size); diff --git a/arch/ia64/mm/numa.c b/arch/ia64/mm/numa.c index 34752bedd504..ef2dbcfdad80 100644 --- a/arch/ia64/mm/numa.c +++ b/arch/ia64/mm/numa.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -21,7 +20,6 @@ #include #include -static struct memblk *sysfs_memblks; static struct node *sysfs_nodes; static struct cpu *sysfs_cpus; @@ -29,8 +27,8 @@ static struct cpu *sysfs_cpus; * The following structures are usually initialized by ACPI or * similar mechanisms and describe the NUMA characteristics of the machine. */ -int num_memblks; -struct node_memblk_s node_memblk[NR_MEMBLKS]; +int num_node_memblks; +struct node_memblk_s node_memblk[NR_NODE_MEMBLKS]; struct node_cpuid_s node_cpuid[NR_CPUS]; /* * This is a matrix with "distances" between nodes, they should be @@ -44,12 +42,12 @@ paddr_to_nid(unsigned long paddr) { int i; - for (i = 0; i < num_memblks; i++) + for (i = 0; i < num_node_memblks; i++) if (paddr >= node_memblk[i].start_paddr && paddr < node_memblk[i].start_paddr + node_memblk[i].size) break; - return (i < num_memblks) ? node_memblk[i].nid : (num_memblks ? -1 : 0); + return (i < num_node_memblks) ? node_memblk[i].nid : (num_node_memblks ? -1 : 0); } static int __init topology_init(void) @@ -63,18 +61,8 @@ static int __init topology_init(void) } memset(sysfs_nodes, 0, sizeof(struct node) * numnodes); - sysfs_memblks = kmalloc(sizeof(struct memblk) * num_memblks, - GFP_KERNEL); - if (!sysfs_memblks) { - kfree(sysfs_nodes); - err = -ENOMEM; - goto out; - } - memset(sysfs_memblks, 0, sizeof(struct memblk) * num_memblks); - sysfs_cpus = kmalloc(sizeof(struct cpu) * NR_CPUS, GFP_KERNEL); if (!sysfs_cpus) { - kfree(sysfs_memblks); kfree(sysfs_nodes); err = -ENOMEM; goto out; @@ -85,11 +73,6 @@ static int __init topology_init(void) if ((err = register_node(&sysfs_nodes[i], i, 0))) goto out; - for (i = 0; i < num_memblks; i++) - if ((err = register_memblk(&sysfs_memblks[i], i, - &sysfs_nodes[memblk_to_node(i)]))) - goto out; - for (i = 0; i < NR_CPUS; i++) if (cpu_online(i)) if((err = register_cpu(&sysfs_cpus[i], i, diff --git a/drivers/base/Makefile b/drivers/base/Makefile index e19ffda6cdba..0edaebead032 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile @@ -5,4 +5,4 @@ obj-y := core.o sys.o interface.o bus.o \ cpu.o firmware.o init.o map.o obj-y += power/ obj-$(CONFIG_FW_LOADER) += firmware_class.o -obj-$(CONFIG_NUMA) += node.o memblk.o +obj-$(CONFIG_NUMA) += node.o diff --git a/drivers/base/memblk.c b/drivers/base/memblk.c deleted file mode 100644 index 67f989f5711e..000000000000 --- a/drivers/base/memblk.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * drivers/base/memblk.c - basic Memory Block class support - */ - -#include -#include -#include -#include -#include - - -static struct sysdev_class memblk_class = { - set_kset_name("memblk"), -}; - -/* - * register_memblk - Setup a driverfs device for a MemBlk - * @num - MemBlk number to use when creating the device. - * - * Initialize and register the MemBlk device. - */ -int __init register_memblk(struct memblk *memblk, int num, struct node *root) -{ - int error; - - memblk->node_id = memblk_to_node(num); - memblk->sysdev.cls = &memblk_class, - memblk->sysdev.id = num; - - error = sys_device_register(&memblk->sysdev); - if (!error) - error = sysfs_create_link(&root->sysdev.kobj, - &memblk->sysdev.kobj, - kobject_name(&memblk->sysdev.kobj)); - return error; -} - - -int __init register_memblk_type(void) -{ - return sysdev_class_register(&memblk_class); -} -postcore_initcall(register_memblk_type); diff --git a/include/asm-alpha/topology.h b/include/asm-alpha/topology.h index dbdb0d4f90e1..65a6a2e8b6a1 100644 --- a/include/asm-alpha/topology.h +++ b/include/asm-alpha/topology.h @@ -39,9 +39,6 @@ static inline int node_to_cpumask(int node) return node_cpu_mask; } -# define node_to_memblk(node) (node) -# define memblk_to_node(memblk) (memblk) - /* Cross-node load balancing interval. */ # define NODE_BALANCE_RATE 10 diff --git a/include/asm-generic/topology.h b/include/asm-generic/topology.h index ba29df93e8eb..8f84159f0f4b 100644 --- a/include/asm-generic/topology.h +++ b/include/asm-generic/topology.h @@ -32,9 +32,6 @@ #ifndef cpu_to_node #define cpu_to_node(cpu) (0) #endif -#ifndef memblk_to_node -#define memblk_to_node(memblk) (0) -#endif #ifndef parent_node #define parent_node(node) (0) #endif @@ -44,9 +41,6 @@ #ifndef node_to_first_cpu #define node_to_first_cpu(node) (0) #endif -#ifndef node_to_memblk -#define node_to_memblk(node) (0) -#endif #ifndef pcibus_to_cpumask #define pcibus_to_cpumask(bus) (cpu_online_map) #endif diff --git a/include/asm-i386/memblk.h b/include/asm-i386/memblk.h deleted file mode 100644 index 668fc0d644ba..000000000000 --- a/include/asm-i386/memblk.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _ASM_I386_MEMBLK_H_ -#define _ASM_I386_MEMBLK_H_ - -#include -#include -#include -#include - -#include - -struct i386_memblk { - struct memblk memblk; -}; -extern struct i386_memblk memblk_devices[MAX_NR_MEMBLKS]; - -static inline int arch_register_memblk(int num){ - int p_node = memblk_to_node(num); - - return register_memblk(&memblk_devices[num].memblk, num, - &node_devices[p_node].node); -} - -#endif /* _ASM_I386_MEMBLK_H_ */ diff --git a/include/asm-i386/topology.h b/include/asm-i386/topology.h index 9190a4f3408f..219c6efbd972 100644 --- a/include/asm-i386/topology.h +++ b/include/asm-i386/topology.h @@ -43,9 +43,6 @@ static inline int cpu_to_node(int cpu) return cpu_2_node[cpu]; } -/* Returns the number of the node containing MemBlk 'memblk' */ -#define memblk_to_node(memblk) (memblk) - /* Returns the number of the node containing Node 'node'. This architecture is flat, so it is a pretty simple function! */ #define parent_node(node) (node) @@ -63,9 +60,6 @@ static inline int node_to_first_cpu(int node) return first_cpu(mask); } -/* Returns the number of the first MemBlk on Node 'node' */ -#define node_to_memblk(node) (node) - /* Returns the number of the node containing PCI bus 'bus' */ static inline cpumask_t pcibus_to_cpumask(int bus) { diff --git a/include/asm-ia64/mmzone.h b/include/asm-ia64/mmzone.h index 9b9afd467f76..f28f0b28504f 100644 --- a/include/asm-ia64/mmzone.h +++ b/include/asm-ia64/mmzone.h @@ -20,11 +20,11 @@ #ifdef CONFIG_IA64_DIG /* DIG systems are small */ # define MAX_PHYSNODE_ID 8 # define NR_NODES 8 -# define NR_MEMBLKS (NR_NODES * 32) +# define NR_NODE_MEMBLKS (NR_NODES * 8) #else /* sn2 is the biggest case, so we use that if !DIG */ # define MAX_PHYSNODE_ID 2048 # define NR_NODES 256 -# define NR_MEMBLKS (NR_NODES) +# define NR_NODE_MEMBLKS (NR_NODES * 4) #endif extern unsigned long max_low_pfn; @@ -34,6 +34,6 @@ extern unsigned long max_low_pfn; #define pfn_to_page(pfn) (vmem_map + (pfn)) #else /* CONFIG_DISCONTIGMEM */ -# define NR_MEMBLKS 1 +# define NR_NODE_MEMBLKS 4 #endif /* CONFIG_DISCONTIGMEM */ #endif /* _ASM_IA64_MMZONE_H */ diff --git a/include/asm-ia64/numa.h b/include/asm-ia64/numa.h index de73c7000a52..6459f619a497 100644 --- a/include/asm-ia64/numa.h +++ b/include/asm-ia64/numa.h @@ -28,7 +28,7 @@ extern cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned; /* Stuff below this line could be architecture independent */ -extern int num_memblks; /* total number of memory chunks */ +extern int num_node_memblks; /* total number of memory chunks */ /* * List of node memory chunks. Filled when parsing SRAT table to @@ -47,7 +47,7 @@ struct node_cpuid_s { int nid; /* logical node containing this CPU */ }; -extern struct node_memblk_s node_memblk[NR_MEMBLKS]; +extern struct node_memblk_s node_memblk[NR_NODE_MEMBLKS]; extern struct node_cpuid_s node_cpuid[NR_CPUS]; /* diff --git a/include/asm-ia64/topology.h b/include/asm-ia64/topology.h index f6b971b5267c..d4105bd76489 100644 --- a/include/asm-ia64/topology.h +++ b/include/asm-ia64/topology.h @@ -28,15 +28,6 @@ */ #define node_to_cpumask(node) (node_to_cpu_mask[node]) -/* - * Returns the number of the node containing MemBlk 'memblk' - */ -#ifdef CONFIG_ACPI_NUMA -#define memblk_to_node(memblk) (node_memblk[memblk].nid) -#else -#define memblk_to_node(memblk) (memblk) -#endif - /* * Returns the number of the node containing Node 'nid'. * Not implemented here. Multi-level hierarchies detected with @@ -49,12 +40,6 @@ */ #define node_to_first_cpu(node) (__ffs(node_to_cpumask(node))) -/* - * Returns the number of the first MemBlk on Node 'node' - * Should be fixed when IA64 discontigmem goes in. - */ -#define node_to_memblk(node) (node) - /* Cross-node load balancing interval. */ #define NODE_BALANCE_RATE 10 diff --git a/include/asm-ppc64/topology.h b/include/asm-ppc64/topology.h index a41ca6cba882..c6846ecfaf8b 100644 --- a/include/asm-ppc64/topology.h +++ b/include/asm-ppc64/topology.h @@ -19,8 +19,6 @@ static inline int cpu_to_node(int cpu) return node; } -#define memblk_to_node(memblk) (memblk) - #define parent_node(node) (node) static inline cpumask_t node_to_cpumask(int node) @@ -35,8 +33,6 @@ static inline int node_to_first_cpu(int node) return first_cpu(tmp); } -#define node_to_memblk(node) (node) - #define pcibus_to_cpumask(bus) (cpu_online_map) #define nr_cpus_node(node) (nr_cpus_in_node[node]) diff --git a/include/asm-x86_64/memblk.h b/include/asm-x86_64/memblk.h deleted file mode 100644 index cb084c244f0d..000000000000 --- a/include/asm-x86_64/memblk.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/include/asm-x86_64/topology.h b/include/asm-x86_64/topology.h index 1a614e8c0b18..02b24f4ef8d9 100644 --- a/include/asm-x86_64/topology.h +++ b/include/asm-x86_64/topology.h @@ -15,11 +15,9 @@ extern int fake_node; extern unsigned long cpu_online_map; #define cpu_to_node(cpu) (fake_node ? 0 : (cpu)) -#define memblk_to_node(memblk) (fake_node ? 0 : (memblk)) #define parent_node(node) (node) #define node_to_first_cpu(node) (fake_node ? 0 : (node)) #define node_to_cpumask(node) (fake_node ? cpu_online_map : (1UL << (node))) -#define node_to_memblk(node) (node) static inline unsigned long pcibus_to_cpumask(int bus) { diff --git a/include/linux/memblk.h b/include/linux/memblk.h deleted file mode 100644 index 5f216fb47907..000000000000 --- a/include/linux/memblk.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * include/linux/memblk.h - generic memblk definition - * - * This is mainly for topological representation. We define the - * basic 'struct memblk' here, which can be embedded in per-arch - * definitions of memory blocks. - * - * Basic handling of the devices is done in drivers/base/memblk.c - * and system devices are handled in drivers/base/sys.c. - * - * MemBlks are exported via driverfs in the class/memblk/devices/ - * directory. - * - * Per-memblk interfaces can be implemented using a struct device_interface. - * See the following for how to do this: - * - drivers/base/intf.c - * - Documentation/driver-model/interface.txt - */ -#ifndef _LINUX_MEMBLK_H_ -#define _LINUX_MEMBLK_H_ - -#include -#include - -struct memblk { - int node_id; /* The node which contains the MemBlk */ - struct sys_device sysdev; -}; - -extern int register_memblk(struct memblk *, int, struct node *); - -#endif /* _LINUX_MEMBLK_H_ */ diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 71f2f39cae0f..179f51f29f78 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -294,12 +294,6 @@ struct file; int min_free_kbytes_sysctl_handler(struct ctl_table *, int, struct file *, void *, size_t *); -#ifdef CONFIG_NUMA -#define MAX_NR_MEMBLKS BITS_PER_LONG /* Max number of Memory Blocks */ -#else /* !CONFIG_NUMA */ -#define MAX_NR_MEMBLKS 1 -#endif /* CONFIG_NUMA */ - #include /* Returns the number of the current Node. */ #define numa_node_id() (cpu_to_node(smp_processor_id())) @@ -342,7 +336,6 @@ extern struct pglist_data contig_page_data; #endif extern DECLARE_BITMAP(node_online_map, MAX_NUMNODES); -extern DECLARE_BITMAP(memblk_online_map, MAX_NR_MEMBLKS); #if defined(CONFIG_DISCONTIGMEM) || defined(CONFIG_NUMA) @@ -360,20 +353,6 @@ static inline unsigned int num_online_nodes(void) return num; } -#define memblk_online(memblk) test_bit(memblk, memblk_online_map) -#define memblk_set_online(memblk) set_bit(memblk, memblk_online_map) -#define memblk_set_offline(memblk) clear_bit(memblk, memblk_online_map) -static inline unsigned int num_online_memblks(void) -{ - int i, num = 0; - - for(i = 0; i < MAX_NR_MEMBLKS; i++){ - if (memblk_online(i)) - num++; - } - return num; -} - #else /* !CONFIG_DISCONTIGMEM && !CONFIG_NUMA */ #define node_online(node) \ @@ -384,14 +363,6 @@ static inline unsigned int num_online_memblks(void) ({ BUG_ON((node) != 0); clear_bit(node, node_online_map); }) #define num_online_nodes() 1 -#define memblk_online(memblk) \ - ({ BUG_ON((memblk) != 0); test_bit(memblk, memblk_online_map); }) -#define memblk_set_online(memblk) \ - ({ BUG_ON((memblk) != 0); set_bit(memblk, memblk_online_map); }) -#define memblk_set_offline(memblk) \ - ({ BUG_ON((memblk) != 0); clear_bit(memblk, memblk_online_map); }) -#define num_online_memblks() 1 - #endif /* CONFIG_DISCONTIGMEM || CONFIG_NUMA */ #endif /* !__ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 0a6832b028b5..c73033e4ee47 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -35,7 +35,6 @@ #include DECLARE_BITMAP(node_online_map, MAX_NUMNODES); -DECLARE_BITMAP(memblk_online_map, MAX_NR_MEMBLKS); struct pglist_data *pgdat_list; unsigned long totalram_pages; unsigned long totalhigh_pages; @@ -1374,7 +1373,6 @@ void __init free_area_init_node(int nid, struct pglist_data *pgdat, pgdat->node_mem_map = node_mem_map; free_area_init_core(pgdat, zones_size, zholes_size); - memblk_set_online(node_to_memblk(nid)); } #ifndef CONFIG_DISCONTIGMEM -- cgit v1.2.3 From 03718ae0c12130f6e2d24312b671f25466414dde Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:47:54 -0800 Subject: [PATCH] Fine tune the time conversion to eliminate conversion errors. From: George Anzinger The time conversion code is erroring on the side of a bit too small. The attached patch forces any error to be on the high side. The current code will convert 1 nanosecond to zero jiffies (standard says that should be 1). It also is around 1 nanosecond late on each roll to the next jiffie. I have done some error checks with this patch applied and get the following errors in PPB ( Parts Per Billion): HZ nano sec conversion microsecond conversion 1000 315 45 1024 227 40 100 28 317 In all cases the error is on the high side, which means that the final shift will, most likely, eliminate the error bits. --- include/linux/time.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/include/linux/time.h b/include/linux/time.h index 891bf4607d16..b85d596949a3 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -148,14 +148,14 @@ struct timezone { #endif #define NSEC_JIFFIE_SC (SEC_JIFFIE_SC + 29) #define USEC_JIFFIE_SC (SEC_JIFFIE_SC + 19) -#define SEC_CONVERSION ((unsigned long)((((u64)NSEC_PER_SEC << SEC_JIFFIE_SC))\ - / (u64)TICK_NSEC)) +#define SEC_CONVERSION ((unsigned long)((((u64)NSEC_PER_SEC << SEC_JIFFIE_SC) +\ + TICK_NSEC -1) / (u64)TICK_NSEC)) -#define NSEC_CONVERSION ((unsigned long)((((u64)1 << NSEC_JIFFIE_SC))\ - / (u64)TICK_NSEC)) +#define NSEC_CONVERSION ((unsigned long)((((u64)1 << NSEC_JIFFIE_SC) +\ + TICK_NSEC -1) / (u64)TICK_NSEC)) #define USEC_CONVERSION \ - ((unsigned long)((((u64)NSEC_PER_USEC << USEC_JIFFIE_SC)) \ - / (u64)TICK_NSEC)) + ((unsigned long)((((u64)NSEC_PER_USEC << USEC_JIFFIE_SC) +\ + TICK_NSEC -1) / (u64)TICK_NSEC)) /* * USEC_ROUND is used in the timeval to jiffie conversion. See there * for more details. It is the scaled resolution rounding value. Note -- cgit v1.2.3 From a9b9b3c5ebb3f8d4814c10baf7176fd8711d063f Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:48:56 -0800 Subject: [PATCH] ide-cd mo write protect From: Jens Axboe It's from Pascal Schmidt and adds write protect handling to ide-cd along with support for non-2kb block sizes. --- drivers/cdrom/cdrom.c | 34 ++++++++++++++-- drivers/ide/ide-cd.c | 105 ++++++++++++++++++++++++++++---------------------- include/linux/cdrom.h | 1 + 3 files changed, 91 insertions(+), 49 deletions(-) (limited to 'include/linux') diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 54ac0ba508be..bcad7f245618 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -695,6 +695,35 @@ static int cdrom_mrw_open_write(struct cdrom_device_info *cdi) return ret; } +static int mo_open_write(struct cdrom_device_info *cdi) +{ + struct cdrom_generic_command cgc; + char buffer[255]; + int ret; + + init_cdrom_command(&cgc, &buffer, 4, CGC_DATA_READ); + cgc.quiet = 1; + + /* + * obtain write protect information as per + * drivers/scsi/sd.c:sd_read_write_protect_flag + */ + + ret = cdrom_mode_sense(cdi, &cgc, GPMODE_ALL_PAGES, 0); + if (ret) + ret = cdrom_mode_sense(cdi, &cgc, GPMODE_VENDOR_PAGE, 0); + if (ret) { + cgc.buflen = 255; + ret = cdrom_mode_sense(cdi, &cgc, GPMODE_ALL_PAGES, 0); + } + + /* drive gave us no info, let the user go ahead */ + if (ret) + return 0; + + return buffer[3] & 0x80; +} + /* * returns 0 for ok to open write, non-0 to disallow */ @@ -706,11 +735,8 @@ static int cdrom_open_write(struct cdrom_device_info *cdi) ret = cdrom_mrw_open_write(cdi); else if (CDROM_CAN(CDC_DVD_RAM)) ret = cdrom_dvdram_open_write(cdi); - /* - * needs to really check whether media is writeable - */ else if (CDROM_CAN(CDC_MO_DRIVE)) - ret = 0; + ret = mo_open_write(cdi); return ret; } diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index ca6e4a7dfaf5..6aaf3bb8ad05 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -294,10 +294,12 @@ * 4.60 Dec 17, 2003 - Add mt rainier support * - Bump timeout for packet commands, matches sr * - Odd stuff + * 4.61 Jan 22, 2004 - support hardware sector sizes other than 2kB, + * Pascal Schmidt * *************************************************************************/ -#define IDECD_VERSION "4.60" +#define IDECD_VERSION "4.61" #include #include @@ -818,6 +820,14 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) do_end_request = 1; } else if (sense_key == ILLEGAL_REQUEST || sense_key == DATA_PROTECT) { + /* + * check if this was a write protected media + */ + if (rq_data_dir(rq) == WRITE) { + printk("ide-cd: media marked write protected\n"); + set_disk_ro(drive->disk, 1); + } + /* No point in retrying after an illegal request or data protect error.*/ ide_dump_status (drive, "command error", stat); @@ -1211,6 +1221,9 @@ static int cdrom_read_from_buffer (ide_drive_t *drive) { struct cdrom_info *info = drive->driver_data; struct request *rq = HWGROUP(drive)->rq; + unsigned short sectors_per_frame; + + sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS; /* Can't do anything if there's no buffer. */ if (info->buffer == NULL) return 0; @@ -1249,7 +1262,7 @@ static int cdrom_read_from_buffer (ide_drive_t *drive) will fail. I think that this will never happen, but let's be paranoid and check. */ if (rq->current_nr_sectors < bio_cur_sectors(rq->bio) && - (rq->sector % SECTORS_PER_FRAME) != 0) { + (rq->sector & (sectors_per_frame - 1))) { printk("%s: cdrom_read_from_buffer: buffer botch (%ld)\n", drive->name, (long)rq->sector); cdrom_end_request(drive, 0); @@ -1268,13 +1281,10 @@ static int cdrom_read_from_buffer (ide_drive_t *drive) static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive) { struct request *rq = HWGROUP(drive)->rq; - int nsect, sector, nframes, frame, nskip; + unsigned short sectors_per_frame; + int nskip; - /* Number of sectors to transfer. */ - nsect = rq->nr_sectors; - - /* Starting sector. */ - sector = rq->sector; + sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS; /* If the requested sector doesn't start on a cdrom block boundary, we must adjust the start of the transfer so that it does, @@ -1283,31 +1293,19 @@ static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive) of the buffer, it will mean that we're to skip a number of sectors equal to the amount by which CURRENT_NR_SECTORS is larger than the buffer size. */ - nskip = (sector % SECTORS_PER_FRAME); + nskip = rq->sector & (sectors_per_frame - 1); if (nskip > 0) { /* Sanity check... */ if (rq->current_nr_sectors != bio_cur_sectors(rq->bio) && - (rq->sector % CD_FRAMESIZE != 0)) { + (rq->sector & (sectors_per_frame - 1))) { printk ("%s: cdrom_start_read_continuation: buffer botch (%u)\n", drive->name, rq->current_nr_sectors); cdrom_end_request(drive, 0); return ide_stopped; } - sector -= nskip; - nsect += nskip; rq->current_nr_sectors += nskip; } - /* Convert from sectors to cdrom blocks, rounding up the transfer - length if needed. */ - nframes = (nsect + SECTORS_PER_FRAME-1) / SECTORS_PER_FRAME; - frame = sector / SECTORS_PER_FRAME; - - /* Largest number of frames was can transfer at once is 64k-1. For - some drives we need to limit this even more. */ - nframes = MIN (nframes, (CDROM_CONFIG_FLAGS (drive)->limit_nframes) ? - (65534 / CD_FRAMESIZE) : 65535); - /* Set up the command */ rq->timeout = ATAPI_WAIT_PC; @@ -1346,13 +1344,9 @@ static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive) static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive) { struct request *rq = HWGROUP(drive)->rq; - int sector, frame, nskip; + int frame = rq->sector; - sector = rq->sector; - nskip = (sector % SECTORS_PER_FRAME); - if (nskip > 0) - sector -= nskip; - frame = sector / SECTORS_PER_FRAME; + sector_div(frame, queue_hardsect_size(drive->queue) >> SECTOR_BITS); memset(rq->cmd, 0, sizeof(rq->cmd)); rq->cmd[0] = GPCMD_SEEK; @@ -1396,6 +1390,9 @@ static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block) { struct cdrom_info *info = drive->driver_data; struct request *rq = HWGROUP(drive)->rq; + unsigned short sectors_per_frame; + + sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS; /* We may be retrying this request after an error. Fix up any weirdness which might be present in the request packet. */ @@ -1411,10 +1408,9 @@ static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block) info->nsectors_buffered = 0; /* use dma, if possible. */ - if (drive->using_dma && (rq->sector % SECTORS_PER_FRAME == 0) && - (rq->nr_sectors % SECTORS_PER_FRAME == 0)) - info->dma = 1; - else + info->dma = drive->using_dma; + if ((rq->sector & (sectors_per_frame - 1)) || + (rq->nr_sectors & (sectors_per_frame - 1))) info->dma = 0; info->cmd = READ; @@ -1950,11 +1946,22 @@ static ide_startstop_t cdrom_start_write_cont(ide_drive_t *drive) static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq) { struct cdrom_info *info = drive->driver_data; + struct gendisk *g = drive->disk; + unsigned short sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS; + + /* + * writes *must* be hardware frame aligned + */ + if ((rq->nr_sectors & (sectors_per_frame - 1)) || + (rq->sector & (sectors_per_frame - 1))) { + cdrom_end_request(drive, 0); + return ide_stopped; + } /* - * writes *must* be 2kB frame aligned + * disk has become write protected */ - if ((rq->nr_sectors & 3) || (rq->sector & 3)) { + if (g->policy) { cdrom_end_request(drive, 0); return ide_stopped; } @@ -1969,12 +1976,12 @@ static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq) info->nsectors_buffered = 0; - /* use dma, if possible. we don't need to check more, since we - * know that the transfer is always (at least!) 2KB aligned */ + /* use dma, if possible. we don't need to check more, since we + * know that the transfer is always (at least!) frame aligned */ info->dma = drive->using_dma ? 1 : 0; info->cmd = WRITE; - /* Start sending the read request to the drive. */ + /* Start sending the write request to the drive. */ return cdrom_start_packet_command(drive, 32768, cdrom_start_write_cont); } @@ -2209,6 +2216,7 @@ static int cdrom_eject(ide_drive_t *drive, int ejectflag, } static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, + unsigned long *sectors_per_frame, struct request_sense *sense) { struct { @@ -2227,8 +2235,11 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, req.data_len = sizeof(capbuf); stat = cdrom_queue_packet_command(drive, &req); - if (stat == 0) + if (stat == 0) { *capacity = 1 + be32_to_cpu(capbuf.lba); + *sectors_per_frame = + be32_to_cpu(capbuf.blocklen) >> SECTOR_BITS; + } return stat; } @@ -2270,6 +2281,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) struct atapi_toc_entry ent; } ms_tmp; long last_written; + unsigned long sectors_per_frame = SECTORS_PER_FRAME; if (toc == NULL) { /* Try to allocate space. */ @@ -2289,12 +2301,15 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) if (CDROM_STATE_FLAGS(drive)->toc_valid) return 0; - /* Try to get the total cdrom capacity. */ - stat = cdrom_read_capacity(drive, &toc->capacity, sense); + /* Try to get the total cdrom capacity and sector size. */ + stat = cdrom_read_capacity(drive, &toc->capacity, §ors_per_frame, + sense); if (stat) toc->capacity = 0x1fffff; - set_capacity(drive->disk, toc->capacity * SECTORS_PER_FRAME); + set_capacity(drive->disk, toc->capacity * sectors_per_frame); + blk_queue_hardsect_size(drive->queue, + sectors_per_frame << SECTOR_BITS); /* First read just the header, so we know how long the TOC is. */ stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr, @@ -2406,7 +2421,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) stat = cdrom_get_last_written(cdi, &last_written); if (!stat && last_written) { toc->capacity = last_written; - set_capacity(drive->disk, toc->capacity * SECTORS_PER_FRAME); + set_capacity(drive->disk, toc->capacity * sectors_per_frame); } /* Remember that we've read this stuff. */ @@ -3306,12 +3321,12 @@ int ide_cdrom_setup (ide_drive_t *drive) static sector_t ide_cdrom_capacity (ide_drive_t *drive) { - unsigned long capacity; + unsigned long capacity, sectors_per_frame; - if (cdrom_read_capacity(drive, &capacity, NULL)) + if (cdrom_read_capacity(drive, &capacity, §ors_per_frame, NULL)) return 0; - return capacity * SECTORS_PER_FRAME; + return capacity * sectors_per_frame; } static diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h index 1b00b5f96c0b..513ac8f4e9a2 100644 --- a/include/linux/cdrom.h +++ b/include/linux/cdrom.h @@ -496,6 +496,7 @@ struct cdrom_generic_command #define GPCMD_GET_MEDIA_STATUS 0xda /* Mode page codes for mode sense/set */ +#define GPMODE_VENDOR_PAGE 0x00 #define GPMODE_R_W_ERROR_PAGE 0x01 #define GPMODE_WRITE_PARMS_PAGE 0x05 #define GPMODE_AUDIO_CTL_PAGE 0x0e -- cgit v1.2.3 From 48ceccc134ccbd42007b34589e94a908794b5f14 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:49:59 -0800 Subject: [PATCH] Move cpu_vm_mask to be closer to mmu_context_t in struct mm From: Jack Steiner The cpu_vm_mask use to be close to the mmu_context_t field in the mm struct. Recently some large members were added between "cpu_vm_mask" and "context". I suspect that was an oversight. Here is a patch that puts the fields close together. This makes it likely that both fields are in the same cache line. Since both fields are likely to be updated at the same time, this may improve performance. --- include/linux/sched.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/sched.h b/include/linux/sched.h index e77f1330d90b..ac22951d5927 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -204,7 +204,6 @@ struct mm_struct { unsigned long arg_start, arg_end, env_start, env_end; unsigned long rss, total_vm, locked_vm; unsigned long def_flags; - cpumask_t cpu_vm_mask; unsigned long saved_auxv[40]; /* for /proc/PID/auxv */ @@ -212,6 +211,8 @@ struct mm_struct { #ifdef CONFIG_HUGETLB_PAGE int used_hugetlb; #endif + cpumask_t cpu_vm_mask; + /* Architecture-specific MM context */ mm_context_t context; -- cgit v1.2.3 From 30575f5df7eff7fe3d17d6d162d156a8f061250a Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:50:46 -0800 Subject: [PATCH] Remove the unused kmalloc_percpu_init() From: Martin Hicks This patch removes kmalloc_percpu_init() from include/linux/percpu.h It is unused and doesn't seem to be required. --- include/linux/percpu.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/percpu.h b/include/linux/percpu.h index 9e637260e58f..6aedd71cc02c 100644 --- a/include/linux/percpu.h +++ b/include/linux/percpu.h @@ -35,7 +35,6 @@ struct percpu_data { extern void *__alloc_percpu(size_t size, size_t align); extern void free_percpu(const void *); -extern void kmalloc_percpu_init(void); #else /* CONFIG_SMP */ @@ -52,7 +51,6 @@ static inline void free_percpu(const void *ptr) { kfree(ptr); } -static inline void kmalloc_percpu_init(void) { } #endif /* CONFIG_SMP */ -- cgit v1.2.3 From 4df5d868efc9a1c3ff3597df384f6e37ee54e672 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 3 Feb 2004 18:54:15 -0800 Subject: [PATCH] Fix ptrace in the vsyscall dso area From: Roland McGrath The #include is the part of this patch that matters, so the #ifdef below works. The rest of the patch removes gratuitous duplication due to some strange aversion to concision in the presence of #ifdef, the kind that is all too common, utterly pointless, and error prone. --- include/linux/mm.h | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'include/linux') diff --git a/include/linux/mm.h b/include/linux/mm.h index 3ecd3d633c5f..ffc1e13d0a55 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -12,6 +12,7 @@ #include #include #include +#include #ifndef CONFIG_DISCONTIGMEM /* Don't use mapnrs, do it properly */ extern unsigned long max_mapnr; @@ -643,31 +644,24 @@ kernel_map_pages(struct page *page, int numpages, int enable) #endif #ifndef CONFIG_ARCH_GATE_AREA -#ifdef AT_SYSINFO_EHDR static inline int in_gate_area(struct task_struct *task, unsigned long addr) { +#ifdef AT_SYSINFO_EHDR if ((addr >= FIXADDR_USER_START) && (addr < FIXADDR_USER_END)) return 1; - else - return 0; +#endif + return 0; } extern struct vm_area_struct gate_vma; static inline struct vm_area_struct *get_gate_vma(struct task_struct *tsk) { +#ifdef AT_SYSINFO_EHDR return &gate_vma; -} #else -static inline int in_gate_area(struct task_struct *task, unsigned long addr) -{ return 0; -} - -static inline struct vm_area_struct *get_gate_vma(struct task_struct *tsk) -{ - return NULL; -} #endif +} #endif #endif /* __KERNEL__ */ -- cgit v1.2.3 From 2ee0e091335ae675b93433e9d97533fd74789232 Mon Sep 17 00:00:00 2001 From: Hideaki Yoshifuji Date: Wed, 4 Feb 2004 07:16:56 -0800 Subject: [IPV6]: Make note in headers about shared socket option numbers. --- include/linux/in6.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'include/linux') diff --git a/include/linux/in6.h b/include/linux/in6.h index 8689112d08f3..5b4e89b1ac68 100644 --- a/include/linux/in6.h +++ b/include/linux/in6.h @@ -183,5 +183,17 @@ struct in6_flowlabel_req #define IPV6_IPSEC_POLICY 34 #define IPV6_XFRM_POLICY 35 +/* + * Multicast: + * Following socket options are shared between IPv4 and IPv6. + * + * MCAST_JOIN_GROUP 42 + * MCAST_BLOCK_SOURCE 43 + * MCAST_UNBLOCK_SOURCE 44 + * MCAST_LEAVE_GROUP 45 + * MCAST_JOIN_SOURCE_GROUP 46 + * MCAST_LEAVE_SOURCE_GROUP 47 + * MCAST_MSFILTER 48 + */ #endif -- cgit v1.2.3 From b0f4ffe8b6437346ee21584bcf95346fb11a339d Mon Sep 17 00:00:00 2001 From: Jeroen Vreeken Date: Wed, 4 Feb 2004 18:48:25 -0500 Subject: [PATCH] hamradio driver fixes I send these a while ago but didn't get a reply. Can you apply these patches for the hamradio drivers? details: + scc.c usage of rtnl lock and register_netdev. + scc.c properly initialize timers. + remove cli() call in 6pack.c + fix init of reused devices and remove cli() + scc.c statistics --- drivers/net/hamradio/6pack.c | 4 ---- drivers/net/hamradio/mkiss.c | 40 ++++++++++++++++++++++++++-------------- drivers/net/hamradio/mkiss.h | 1 + drivers/net/hamradio/scc.c | 10 +++++++++- include/linux/scc.h | 2 +- 5 files changed, 37 insertions(+), 20 deletions(-) (limited to 'include/linux') diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index ea53fe75059a..91ceae8f5339 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -516,7 +516,6 @@ static int sixpack_receive_room(struct tty_struct *tty) static void sixpack_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { unsigned char buf[512]; - unsigned long flags; int count1; struct sixpack *sp = (struct sixpack *) tty->disc_data; @@ -525,10 +524,7 @@ static void sixpack_receive_buf(struct tty_struct *tty, const unsigned char *cp, !netif_running(sp->dev) || !count) return; - save_flags(flags); - cli(); memcpy(buf, cp, count @@ -167,17 +168,17 @@ static inline struct ax_disp *ax_alloc(void) /* If no channels are available, allocate one */ if (axp == NULL && (ax25_ctrls[i] = kmalloc(sizeof(ax25_ctrl_t), GFP_KERNEL)) != NULL) { axp = ax25_ctrls[i]; - memset(axp, 0, sizeof(ax25_ctrl_t)); - - /* Initialize channel control data */ - set_bit(AXF_INUSE, &axp->ctrl.flags); - sprintf(axp->dev.name, "ax%d", i++); - axp->ctrl.tty = NULL; - axp->dev.base_addr = i; - axp->dev.priv = (void *)&axp->ctrl; - axp->dev.next = NULL; - axp->dev.init = ax25_init; } + memset(axp, 0, sizeof(ax25_ctrl_t)); + + /* Initialize channel control data */ + set_bit(AXF_INUSE, &axp->ctrl.flags); + sprintf(axp->dev.name, "ax%d", i++); + axp->ctrl.tty = NULL; + axp->dev.base_addr = i; + axp->dev.priv = (void *)&axp->ctrl; + axp->dev.next = NULL; + axp->dev.init = ax25_init; if (axp != NULL) { /* @@ -220,7 +221,6 @@ static void ax_changedmtu(struct ax_disp *ax) struct net_device *dev = ax->dev; unsigned char *xbuff, *rbuff, *oxbuff, *orbuff; int len; - unsigned long flags; len = dev->mtu * 2; @@ -246,8 +246,7 @@ static void ax_changedmtu(struct ax_disp *ax) return; } - save_flags(flags); - cli(); + spin_lock_bh(ax->buflock); oxbuff = ax->xbuff; ax->xbuff = xbuff; @@ -278,7 +277,7 @@ static void ax_changedmtu(struct ax_disp *ax) ax->mtu = dev->mtu + 73; ax->buffsize = len; - restore_flags(flags); + spin_unlock_bh(ax->buflock); if (oxbuff != NULL) kfree(oxbuff); @@ -306,6 +305,7 @@ static void ax_bump(struct ax_disp *ax) struct sk_buff *skb; int count; + spin_lock_bh(ax->buflock); if (ax->rbuff[0] > 0x0f) { if (ax->rbuff[0] & 0x20) { ax->crcmode = CRC_MODE_FLEX; @@ -322,6 +322,7 @@ static void ax_bump(struct ax_disp *ax) *ax->rbuff &= ~0x20; } } + spin_unlock_bh(ax->buflock); count = ax->rcount; @@ -332,7 +333,9 @@ static void ax_bump(struct ax_disp *ax) } skb->dev = ax->dev; + spin_lock_bh(ax->buflock); memcpy(skb_put(skb,count), ax->rbuff, count); + spin_unlock_bh(ax->buflock); skb->mac.raw = skb->data; skb->protocol = htons(ETH_P_AX25); netif_rx(skb); @@ -360,6 +363,7 @@ static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len) p = icp; + spin_lock_bh(ax->buflock); switch (ax->crcmode) { unsigned short crc; @@ -373,6 +377,7 @@ static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len) count = kiss_esc(p, (unsigned char *)ax->xbuff, len); break; } + ax->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); actual = ax->tty->driver->write(ax->tty, 0, ax->xbuff, count); ax->tx_packets++; @@ -380,6 +385,8 @@ static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len) ax->dev->trans_start = jiffies; ax->xleft = count - actual; ax->xhead = ax->xbuff + actual; + + spin_unlock_bh(ax->buflock); } /* @@ -511,6 +518,8 @@ static int ax_open(struct net_device *dev) ax->flags &= (1 << AXF_INUSE); /* Clear ESCAPE & ERROR flags */ + ax->buflock = SPIN_LOCK_UNLOCKED; + netif_start_queue(dev); return 0; @@ -750,15 +759,18 @@ static void kiss_unesc(struct ax_disp *ax, unsigned char s) break; } + spin_lock_bh(ax->buflock); if (!test_bit(AXF_ERROR, &ax->flags)) { if (ax->rcount < ax->buffsize) { ax->rbuff[ax->rcount++] = s; + spin_unlock_bh(ax->buflock); return; } ax->rx_over_errors++; set_bit(AXF_ERROR, &ax->flags); } + spin_unlock_bh(ax->buflock); } diff --git a/drivers/net/hamradio/mkiss.h b/drivers/net/hamradio/mkiss.h index fa62e76829c8..4ab700478598 100644 --- a/drivers/net/hamradio/mkiss.h +++ b/drivers/net/hamradio/mkiss.h @@ -56,6 +56,7 @@ struct ax_disp { #define CRC_MODE_NONE 0 #define CRC_MODE_FLEX 1 #define CRC_MODE_SMACK 2 + spinlock_t buflock; /* lock for rbuf and xbuf */ }; #define AX25_MAGIC 0x5316 diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c index 7d4afa3bd16a..0e6844fc339b 100644 --- a/drivers/net/hamradio/scc.c +++ b/drivers/net/hamradio/scc.c @@ -163,6 +163,7 @@ #include #include #include +#include #include #include #include @@ -1520,8 +1521,10 @@ static int scc_net_alloc(const char *name, struct scc_channel *scc) dev->priv = scc; scc->dev = dev; spin_lock_init(&scc->lock); + init_timer(&scc->tx_t); + init_timer(&scc->tx_wdog); - err = register_netdev(dev); + err = register_netdevice(dev); if (err) { printk(KERN_ERR "%s: can't register network device (%d)\n", name, err); @@ -1625,6 +1628,7 @@ static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb) } scc->dev_stat.rx_packets++; + scc->dev_stat.rx_bytes += skb->len; skb->dev = scc->dev; skb->protocol = htons(ETH_P_AX25); @@ -1651,6 +1655,7 @@ static int scc_net_tx(struct sk_buff *skb, struct net_device *dev) } scc->dev_stat.tx_packets++; + scc->dev_stat.tx_bytes += skb->len; scc->stat.txframes++; kisscmd = *skb->data & 0x1f; @@ -2114,10 +2119,13 @@ static int __init scc_init_driver (void) sprintf(devname,"%s0", SCC_DriverName); + rtnl_lock(); if (scc_net_alloc(devname, SCC_Info)) { + rtnl_unlock(); printk(KERN_ERR "z8530drv: cannot initialize module\n"); return -EIO; } + rtnl_unlock(); proc_net_fops_create("z8530drv", 0, &scc_net_seq_fops); diff --git a/include/linux/scc.h b/include/linux/scc.h index 4965e146b737..885a4a02b23c 100644 --- a/include/linux/scc.h +++ b/include/linux/scc.h @@ -200,7 +200,7 @@ struct scc_kiss { unsigned char fulldup; /* Full Duplex mode 0=CSMA 1=DUP 2=ALWAYS KEYED */ unsigned char waittime; /* Waittime before any transmit attempt */ unsigned int maxkeyup; /* Maximum time to transmit (seconds) */ - unsigned char mintime; /* Minimal offtime after MAXKEYUP timeout (seconds) */ + unsigned int mintime; /* Minimal offtime after MAXKEYUP timeout (seconds) */ unsigned int idletime; /* Maximum idle time in ALWAYS KEYED mode (seconds) */ unsigned int maxdefer; /* Timer for CSMA channel busy limit */ unsigned char tx_inhibit; /* Transmit is not allowed when set */ -- cgit v1.2.3 From 8d19538bd5e7aa71ff8dac5fbd272bdc17ad6311 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Wed, 4 Feb 2004 16:58:34 -0800 Subject: [PATCH] parport fixes (1/6) Current tree has all allocated ports on portlist. However, most of the portlist users assume that we only have announced ports there and break badly if they happen to see the list after port driver has created a port (parport_register_port()) but before it finishes the setup (and calls parport_announce_port()). The only place that wants to see all allocated port is parport_register_port() itself and only to pick the first unused port number. We add a new list (all_ports) and put ports there when allocated; that list is kept ordered by port->number. Ports are placed on portlist only by parport_announce_port(). Gobs of shite in parport_register_port() removed, pile of races closed... --- drivers/parport/share.c | 75 +++++++++++++++++++++++-------------------------- include/linux/parport.h | 2 ++ 2 files changed, 37 insertions(+), 40 deletions(-) (limited to 'include/linux') diff --git a/drivers/parport/share.c b/drivers/parport/share.c index b6198f69efb0..ccb4f5447cc4 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c @@ -44,6 +44,10 @@ int parport_default_spintime = DEFAULT_SPIN_TIME; static struct parport *portlist = NULL, *portlist_tail = NULL; static spinlock_t parportlist_lock = SPIN_LOCK_UNLOCKED; +/* list of all allocated ports, sorted by ->number */ +static LIST_HEAD(all_ports); +static spinlock_t full_list_lock = SPIN_LOCK_UNLOCKED; + static struct parport_driver *driver_chain = NULL; static spinlock_t driverlist_lock = SPIN_LOCK_UNLOCKED; @@ -284,6 +288,9 @@ void parport_unregister_driver (struct parport_driver *arg) static void free_port (struct parport *port) { int d; + spin_lock(&full_list_lock); + list_del(&port->full_list); + spin_unlock(&full_list_lock); for (d = 0; d < 5; d++) { if (port->probe_info[d].class_name) kfree (port->probe_info[d].class_name); @@ -386,8 +393,9 @@ struct parport *parport_enumerate(void) struct parport *parport_register_port(unsigned long base, int irq, int dma, struct parport_operations *ops) { + struct list_head *l; struct parport *tmp; - int portnum; + int num; int device; char *name; @@ -418,6 +426,7 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma, init_MUTEX_LOCKED (&tmp->ieee1284.irq); /* actually a semaphore at 0 */ tmp->spintime = parport_default_spintime; atomic_set (&tmp->ref_count, 1); + INIT_LIST_HEAD(&tmp->full_list); name = kmalloc(15, GFP_KERNEL); if (!name) { @@ -427,53 +436,22 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma, } /* Search for the lowest free parport number. */ - spin_lock_irq (&parportlist_lock); - for (portnum = 0; ; portnum++) { - struct parport *itr = portlist; - while (itr) { - if (itr->number == portnum) - /* No good, already used. */ - break; - else - itr = itr->next; - } - - if (itr == NULL) - /* Got to the end of the list. */ + spin_lock(&full_list_lock); + for (l = all_ports.next, num = 0; l != &all_ports; l = l->next, num++) { + struct parport *p = list_entry(l, struct parport, full_list); + if (p->number != num) break; } + tmp->portnum = tmp->number = num; + list_add_tail(&tmp->full_list, l); + spin_unlock(&full_list_lock); /* * Now that the portnum is known finish doing the Init. */ - tmp->portnum = tmp->number = portnum; - sprintf(name, "parport%d", portnum); + sprintf(name, "parport%d", tmp->portnum = tmp->number); tmp->name = name; - - /* - * Chain the entry to our list. - * - * This function must not run from an irq handler so we don' t need - * to clear irq on the local CPU. -arca - */ - - /* We are locked against anyone else performing alterations, but - * because of parport_enumerate people can still _read_ the list - * while we are changing it; so be careful.. - * - * It's okay to have portlist_tail a little bit out of sync - * since it's only used for changing the list, not for reading - * from it. - */ - - if (portlist_tail) - portlist_tail->next = tmp; - portlist_tail = tmp; - if (!portlist) - portlist = tmp; - spin_unlock_irq(&parportlist_lock); - for (device = 0; device < 5; device++) /* assume the worst */ tmp->probe_info[device].class = PARPORT_CLASS_LEGACY; @@ -497,6 +475,23 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma, void parport_announce_port (struct parport *port) { + + /* We are locked against anyone else performing alterations, but + * because of parport_enumerate people can still _read_ the list + * while we are changing it; so be careful.. + * + * It's okay to have portlist_tail a little bit out of sync + * since it's only used for changing the list, not for reading + * from it. + */ + + spin_lock_irq(&parportlist_lock); + if (portlist_tail) + portlist_tail->next = port; + portlist_tail = port; + if (!portlist) + portlist = port; + spin_unlock_irq(&parportlist_lock); #ifdef CONFIG_PARPORT_1284 /* Analyse the IEEE1284.3 topology of the port. */ if (parport_daisy_init (port) == 0) { diff --git a/include/linux/parport.h b/include/linux/parport.h index 77e99e8eace2..eff925bb5da6 100644 --- a/include/linux/parport.h +++ b/include/linux/parport.h @@ -311,6 +311,8 @@ struct parport { int spintime; atomic_t ref_count; + + struct list_head full_list; }; #define DEFAULT_SPIN_TIME 500 /* us */ -- cgit v1.2.3 From ae78191f33cde741c4069dd257a05ba61ba6e000 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 4 Feb 2004 20:39:11 -0800 Subject: [PATCH] remove unused ide_devices_t from ide.c and ide.h Introduced in kernel 2.5.35 and never used. --- drivers/ide/ide.c | 12 ------------ include/linux/ide.h | 14 -------------- 2 files changed, 26 deletions(-) (limited to 'include/linux') diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 217385f97a04..8f86f9e7fa2f 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -197,18 +197,6 @@ ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */ EXPORT_SYMBOL(ide_hwifs); -ide_devices_t *idedisk; -ide_devices_t *idecd; -ide_devices_t *idefloppy; -ide_devices_t *idetape; -ide_devices_t *idescsi; - -EXPORT_SYMBOL(idedisk); -EXPORT_SYMBOL(idecd); -EXPORT_SYMBOL(idefloppy); -EXPORT_SYMBOL(idetape); -EXPORT_SYMBOL(idescsi); - extern ide_driver_t idedefault_driver; static void setup_driver_defaults(ide_driver_t *driver); diff --git a/include/linux/ide.h b/include/linux/ide.h index 2b7777338be0..ac844eca377d 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1214,13 +1214,6 @@ typedef struct ide_driver_s { extern int generic_ide_ioctl(struct block_device *, unsigned, unsigned long); -typedef struct ide_devices_s { - char name[4]; /* hdX */ - unsigned attached : 1; /* native */ - unsigned alttached : 1; /* alternate */ - struct ide_devices_s *next; -} ide_devices_t; - /* * ide_hwifs[] is the master data structure used to keep track * of just about everything in ide.c. Whenever possible, routines @@ -1231,13 +1224,6 @@ typedef struct ide_devices_s { */ #ifndef _IDE_C extern ide_hwif_t ide_hwifs[]; /* master data repository */ - -extern ide_devices_t *idedisk; -extern ide_devices_t *idecd; -extern ide_devices_t *idefloppy; -extern ide_devices_t *idetape; -extern ide_devices_t *idescsi; - #endif extern int noautodma; -- cgit v1.2.3 From e1009878163b1224397b3a109654b184c5f96cfc Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 4 Feb 2004 20:39:28 -0800 Subject: [PATCH] remove unused __ide_dma_retune() and ide_hwif_t->ide_dma_retune First introduced in kernel 2.3.99-pre3 (added to ide_dmaproc) and never used. --- drivers/ide/ide-dma.c | 18 ------------------ drivers/ide/ide.c | 1 - drivers/ide/pci/sgiioc4.c | 1 - drivers/ide/ppc/pmac.c | 1 - include/linux/ide.h | 3 --- 5 files changed, 24 deletions(-) (limited to 'include/linux') diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 8864718ef308..09c7b47a968f 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -850,22 +850,6 @@ int __ide_dma_verbose (ide_drive_t *drive) EXPORT_SYMBOL(__ide_dma_verbose); -/** - * __ide_dma_retune - default retune handler - * @drive: drive to retune - * - * Default behaviour when we decide to return the IDE DMA setup. - * The default behaviour is "we don't" - */ - -int __ide_dma_retune (ide_drive_t *drive) -{ - printk(KERN_WARNING "%s: chipset supported call only\n", __FUNCTION__); - return 1; -} - -EXPORT_SYMBOL(__ide_dma_retune); - int __ide_dma_lostirq (ide_drive_t *drive) { printk("%s: DMA interrupt recovery\n", drive->name); @@ -1104,8 +1088,6 @@ void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_p hwif->ide_dma_verbose = &__ide_dma_verbose; if (!hwif->ide_dma_timeout) hwif->ide_dma_timeout = &__ide_dma_timeout; - if (!hwif->ide_dma_retune) - hwif->ide_dma_retune = &__ide_dma_retune; if (!hwif->ide_dma_lostirq) hwif->ide_dma_lostirq = &__ide_dma_lostirq; diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 8f86f9e7fa2f..031e2863d894 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -846,7 +846,6 @@ void ide_unregister (unsigned int index) hwif->ide_dma_good_drive = old_hwif.ide_dma_good_drive; hwif->ide_dma_count = old_hwif.ide_dma_count; hwif->ide_dma_verbose = old_hwif.ide_dma_verbose; - hwif->ide_dma_retune = old_hwif.ide_dma_retune; hwif->ide_dma_lostirq = old_hwif.ide_dma_lostirq; hwif->ide_dma_timeout = old_hwif.ide_dma_timeout; hwif->ide_dma_queued_on = old_hwif.ide_dma_queued_on; diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index 4d8332a9437f..fe8d0888bd88 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c @@ -653,7 +653,6 @@ ide_init_sgiioc4(ide_hwif_t * hwif) hwif->ide_dma_good_drive = &__ide_dma_good_drive; hwif->ide_dma_count = &__ide_dma_count; hwif->ide_dma_verbose = &sgiioc4_ide_dma_verbose; - hwif->ide_dma_retune = &__ide_dma_retune; hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq; hwif->ide_dma_timeout = &__ide_dma_timeout; hwif->INB = &sgiioc4_INB; diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index 7810ebaf8dcd..60706f747151 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -2029,7 +2029,6 @@ pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) hwif->ide_dma_bad_drive = &__ide_dma_bad_drive; hwif->ide_dma_verbose = &__ide_dma_verbose; hwif->ide_dma_timeout = &__ide_dma_timeout; - hwif->ide_dma_retune = &__ide_dma_retune; hwif->ide_dma_lostirq = &pmac_ide_dma_lostirq; hwif->ide_dma_queued_on = &__ide_dma_queued_on; hwif->ide_dma_queued_off = &__ide_dma_queued_off; diff --git a/include/linux/ide.h b/include/linux/ide.h index ac844eca377d..98fe2db57d24 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -799,7 +799,6 @@ typedef struct ide_dma_ops_s { int (*ide_dma_good_drive)(ide_drive_t *drive); int (*ide_dma_count)(ide_drive_t *drive); int (*ide_dma_verbose)(ide_drive_t *drive); - int (*ide_dma_retune)(ide_drive_t *drive); int (*ide_dma_lostirq)(ide_drive_t *drive); int (*ide_dma_timeout)(ide_drive_t *drive); /* dma queued operations */ @@ -945,7 +944,6 @@ typedef struct hwif_s { int (*ide_dma_good_drive)(ide_drive_t *drive); int (*ide_dma_count)(ide_drive_t *drive); int (*ide_dma_verbose)(ide_drive_t *drive); - int (*ide_dma_retune)(ide_drive_t *drive); int (*ide_dma_lostirq)(ide_drive_t *drive); int (*ide_dma_timeout)(ide_drive_t *drive); @@ -1637,7 +1635,6 @@ extern int __ide_dma_bad_drive(ide_drive_t *); extern int __ide_dma_good_drive(ide_drive_t *); extern int __ide_dma_count(ide_drive_t *); extern int __ide_dma_verbose(ide_drive_t *); -extern int __ide_dma_retune(ide_drive_t *); extern int __ide_dma_lostirq(ide_drive_t *); extern int __ide_dma_timeout(ide_drive_t *); -- cgit v1.2.3 From 7fae0977896d9e549486e2f85365310a70a4139d Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 4 Feb 2004 20:39:37 -0800 Subject: [PATCH] remove ide_dma_queued_* ops from ide_hwif_t TCQ code is host independent so remove redundant ide_dma_queued_* ops from ide_hwif_t. If we ever decide to bring back TCQ support this will fix OOPS in ide-disk driver with CONFIG_BLK_DEV_IDE_TCQ_DEFAULT=y and icside/sgiioc4 host drivers (it will also enable TCQ support for these host drivers). Acked by Jens. --- drivers/ide/ide-disk.c | 20 +++++++++----------- drivers/ide/ide-dma.c | 23 +++-------------------- drivers/ide/ide-taskfile.c | 6 ++++-- drivers/ide/ide-tcq.c | 4 ++-- drivers/ide/ide.c | 7 ------- drivers/ide/ppc/pmac.c | 7 ------- include/linux/ide.h | 23 ----------------------- 7 files changed, 18 insertions(+), 72 deletions(-) (limited to 'include/linux') diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index ac2a3ec078ec..cc767670a038 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -470,9 +470,10 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector } if (rq_data_dir(rq) == READ) { +#ifdef CONFIG_BLK_DEV_IDE_TCQ if (blk_rq_tagged(rq)) - return hwif->ide_dma_queued_read(drive); - + return __ide_dma_queued_read(drive); +#endif if (drive->using_dma && !hwif->ide_dma_read(drive)) return ide_started; @@ -483,10 +484,10 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector return ide_started; } else if (rq_data_dir(rq) == WRITE) { ide_startstop_t startstop; - +#ifdef CONFIG_BLK_DEV_IDE_TCQ if (blk_rq_tagged(rq)) - return hwif->ide_dma_queued_write(drive); - + return __ide_dma_queued_write(drive); +#endif if (drive->using_dma && !(HWIF(drive)->ide_dma_write(drive))) return ide_started; @@ -1400,13 +1401,10 @@ static int set_acoustic (ide_drive_t *drive, int arg) #ifdef CONFIG_BLK_DEV_IDE_TCQ static int set_using_tcq(ide_drive_t *drive, int arg) { - ide_hwif_t *hwif = HWIF(drive); int ret; if (!drive->driver) return -EPERM; - if (!hwif->ide_dma_queued_on || !hwif->ide_dma_queued_off) - return -ENXIO; if (arg == drive->queue_depth && drive->using_tcq) return 0; @@ -1420,9 +1418,9 @@ static int set_using_tcq(ide_drive_t *drive, int arg) } if (arg) - ret = HWIF(drive)->ide_dma_queued_on(drive); + ret = __ide_dma_queued_on(drive); else - ret = HWIF(drive)->ide_dma_queued_off(drive); + ret = __ide_dma_queued_off(drive); return ret ? -EIO : 0; } @@ -1673,7 +1671,7 @@ static void idedisk_setup (ide_drive_t *drive) #ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT if (drive->using_dma) - HWIF(drive)->ide_dma_queued_on(drive); + __ide_dma_queued_on(drive); #endif } diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 09c7b47a968f..acf29b5c430a 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -512,9 +512,9 @@ int __ide_dma_off_quietly (ide_drive_t *drive) if (HWIF(drive)->ide_dma_host_off(drive)) return 1; - - HWIF(drive)->ide_dma_queued_off(drive); - +#ifdef CONFIG_BLK_DEV_IDE_TCQ + __ide_dma_queued_off(drive); +#endif return 0; } @@ -1091,23 +1091,6 @@ void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_p if (!hwif->ide_dma_lostirq) hwif->ide_dma_lostirq = &__ide_dma_lostirq; - /* - * dma queued ops. if tcq isn't set, queued on and off are just - * dummy functions. cuts down on ifdef hell - */ - if (!hwif->ide_dma_queued_on) - hwif->ide_dma_queued_on = __ide_dma_queued_on; - if (!hwif->ide_dma_queued_off) - hwif->ide_dma_queued_off = __ide_dma_queued_off; -#ifdef CONFIG_BLK_DEV_IDE_TCQ - if (!hwif->ide_dma_queued_read) - hwif->ide_dma_queued_read = __ide_dma_queued_read; - if (!hwif->ide_dma_queued_write) - hwif->ide_dma_queued_write = __ide_dma_queued_write; - if (!hwif->ide_dma_queued_start) - hwif->ide_dma_queued_start = __ide_dma_queued_start; -#endif - if (hwif->chipset != ide_trm290) { u8 dma_stat = hwif->INB(hwif->dma_status); printk(", BIOS settings: %s:%s, %s:%s", diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 44dc1e03ad3e..eb16f6ec6e28 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -200,12 +200,14 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) if (!hwif->ide_dma_read(drive)) return ide_started; break; +#ifdef CONFIG_BLK_DEV_IDE_TCQ case WIN_READDMA_QUEUED: case WIN_READDMA_QUEUED_EXT: - return hwif->ide_dma_queued_read(drive); + return __ide_dma_queued_read(drive); case WIN_WRITEDMA_QUEUED: case WIN_WRITEDMA_QUEUED_EXT: - return hwif->ide_dma_queued_write(drive); + return __ide_dma_queued_write(drive); +#endif default: if (task->handler == NULL) return ide_stopped; diff --git a/drivers/ide/ide-tcq.c b/drivers/ide/ide-tcq.c index ecf528a45edf..6a432b5a3aee 100644 --- a/drivers/ide/ide-tcq.c +++ b/drivers/ide/ide-tcq.c @@ -353,7 +353,7 @@ ide_startstop_t ide_service(ide_drive_t *drive) */ TCQ_PRINTK("ide_service: starting command, stat=%x\n", stat); spin_unlock_irqrestore(&ide_lock, flags); - return HWIF(drive)->ide_dma_queued_start(drive); + return __ide_dma_queued_start(drive); } printk(KERN_ERR "ide_service: missing request for tag %d\n", tag); @@ -729,7 +729,7 @@ static ide_startstop_t ide_dma_queued_rw(ide_drive_t *drive, u8 command) feat = hwif->INB(IDE_NSECTOR_REG); if (!(feat & REL)) { TCQ_PRINTK("IMMED in queued_start, feat=%x\n", feat); - return hwif->ide_dma_queued_start(drive); + return __ide_dma_queued_start(drive); } /* diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 031e2863d894..8ffdd45a15c4 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -848,13 +848,6 @@ void ide_unregister (unsigned int index) hwif->ide_dma_verbose = old_hwif.ide_dma_verbose; hwif->ide_dma_lostirq = old_hwif.ide_dma_lostirq; hwif->ide_dma_timeout = old_hwif.ide_dma_timeout; - hwif->ide_dma_queued_on = old_hwif.ide_dma_queued_on; - hwif->ide_dma_queued_off = old_hwif.ide_dma_queued_off; -#ifdef CONFIG_BLK_DEV_IDE_TCQ - hwif->ide_dma_queued_read = old_hwif.ide_dma_queued_read; - hwif->ide_dma_queued_write = old_hwif.ide_dma_queued_write; - hwif->ide_dma_queued_start = old_hwif.ide_dma_queued_start; -#endif #endif #if 0 diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index 60706f747151..8612c8d2bc04 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -2030,13 +2030,6 @@ pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) hwif->ide_dma_verbose = &__ide_dma_verbose; hwif->ide_dma_timeout = &__ide_dma_timeout; hwif->ide_dma_lostirq = &pmac_ide_dma_lostirq; - hwif->ide_dma_queued_on = &__ide_dma_queued_on; - hwif->ide_dma_queued_off = &__ide_dma_queued_off; -#ifdef CONFIG_BLK_DEV_IDE_TCQ - hwif->ide_dma_queued_read = __ide_dma_queued_read; - hwif->ide_dma_queued_write = __ide_dma_queued_write; - hwif->ide_dma_queued_start = __ide_dma_queued_start; -#endif #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO if (!noautodma) diff --git a/include/linux/ide.h b/include/linux/ide.h index 98fe2db57d24..f5ee5b62adee 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -801,12 +801,6 @@ typedef struct ide_dma_ops_s { int (*ide_dma_verbose)(ide_drive_t *drive); int (*ide_dma_lostirq)(ide_drive_t *drive); int (*ide_dma_timeout)(ide_drive_t *drive); - /* dma queued operations */ - int (*ide_dma_queued_on)(ide_drive_t *drive); - int (*ide_dma_queued_off)(ide_drive_t *drive); - ide_startstop_t (*ide_dma_queued_read)(ide_drive_t *drive); - ide_startstop_t (*ide_dma_queued_write)(ide_drive_t *drive); - ide_startstop_t (*ide_dma_queued_start)(ide_drive_t *drive); } ide_dma_ops_t; /* @@ -947,13 +941,6 @@ typedef struct hwif_s { int (*ide_dma_lostirq)(ide_drive_t *drive); int (*ide_dma_timeout)(ide_drive_t *drive); - /* dma queued operations */ - int (*ide_dma_queued_on)(ide_drive_t *drive); - int (*ide_dma_queued_off)(ide_drive_t *drive); - ide_startstop_t (*ide_dma_queued_read)(ide_drive_t *drive); - ide_startstop_t (*ide_dma_queued_write)(ide_drive_t *drive); - ide_startstop_t (*ide_dma_queued_start)(ide_drive_t *drive); - void (*OUTB)(u8 addr, unsigned long port); void (*OUTBSYNC)(ide_drive_t *drive, u8 addr, unsigned long port); void (*OUTW)(u16 addr, unsigned long port); @@ -1644,16 +1631,6 @@ extern int __ide_dma_queued_off(ide_drive_t *drive); extern ide_startstop_t __ide_dma_queued_read(ide_drive_t *drive); extern ide_startstop_t __ide_dma_queued_write(ide_drive_t *drive); extern ide_startstop_t __ide_dma_queued_start(ide_drive_t *drive); -#else -static inline int __ide_dma_queued_on(ide_drive_t *drive) -{ - return 1; -} - -static inline int __ide_dma_queued_off(ide_drive_t *drive) -{ - return 1; -} #endif #else -- cgit v1.2.3